QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#292612 | #1295. Fastest Speedrun | snow_trace | WA | 2ms | 9956kb | C++14 | 2.5kb | 2023-12-28 09:34:36 | 2023-12-28 09:34:37 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
const int N = 2505;
int c[N][N],mn_cycle[N][N],mnpos[N][N];vector<int>cycle[N];
#define int long long
vector<int>p[N],p1[N];
int t[N];
int dis[N];int n;
int col[N],vis[N],ok[N];int nw;vector<int>s;
void dfs1(int now){
col[now] = nw;
for(int i =0;i<p[now].size();i++)if(!col[p[now][i]])dfs1(p[now][i]);
}void dfs2(int now,int c,int id){
if(vis[now] == id){
//cout << 111 << endl;
while(s.back()!=now){
cycle[c].push_back(s.back());s.pop_back();
}cycle[c].push_back(now);s.pop_back();
//for(int x:cycle[c])cout << x << " ";cout << endl;
return;
}vis[now] = id;s.push_back(now);
for(int i =0;i<p1[now].size();i++){
//cout<< ' '<<p1[now][i] << " " << vis[p1[now][i]] << endl;
if(!vis[p1[now][i]] or vis[p1[now][i]]==id)dfs2(p1[now][i],c,id);
}return;
}void dfs3(int now,int fa){
for(int i= 0;i<=n;i++)c[now][i] = min(c[now][i],c[fa][i]);
for(int i = 0;i<p1[now].size();i++){
if(ok[p1[now][i]] == 0)dfs3(p1[now][i],now);
}return;
}
signed main(){
cin >> n;
for(int i = 1;i<=n;i++){
int x;cin >> x;p1[x].push_back(i);p[x].push_back(i);p[i].push_back(x);
cin >> t[i];
for(int j = 0;j<=n;j++)cin >> c[i][j];
}for(int i =0;i<=n;i++){
if(!col[i]){
nw++;dfs1(i);
}
}for(int i =0;i<=n;i++){
if(!vis[i]){
dfs2(i,col[i],i+1);s.clear();
}
}for(int i =1;i<=nw;i++){
for(int j = 0;j<=n;j++){
int mn = 2000000005,pos = 0;;
for(int x:cycle[i]){
// cout << x << " ";
if(c[x][j]<mn)mn = c[x][j],pos = x;
}if(i == 1)pos = mn = 0;
mn_cycle[i][j] = mn;mnpos[i][j] = pos;
//cout << endl;
}
}for(int i = 1;i<=nw;i++){
for(int x:cycle[i])ok[x]=1;
}for(int i = 1;i<=nw;i++){
for(int x:cycle[i])dfs3(x,x);
}
int res =0 ;
for(int i = 1;i<=n;i++)if(col[i]!=1)res+=t[i];
for(int i = 1;i<=nw;i++)res+=(mn_cycle[i][n]-t[mnpos[i][n]]);
//cout << res << endl;
for(int i =0;i<=n;i++)dis[i] = 1e18;dis[0] = 0;
for(int i = 1;i<=n;i++){
for(int j =0;j<i;j++){
int cost = min(mn_cycle[col[i]][j]-mn_cycle[col[i]][n],c[i][j]);
dis[i] = min(dis[i],dis[j]+cost);
}
}int ans = res+dis[n];
cout << ans << endl;
return 0;
}
// 经典套路:连边以后是一颗外向基环树,在环里选一个点买下来就能全部跳过激活。
// 然后我们假设最大值一开始就是 n,考虑答案与其差的最小值
// 本质上是我们需要求一个最短路也就是最少多花费多少以后最大的选的点就变成 n
// 激活一个点,两种方式:激活环,激活树上父亲
详细
Test #1:
score: 100
Accepted
time: 1ms
memory: 7920kb
input:
1 1 46655 801493 606509
output:
801493
result:
ok single line: '801493'
Test #2:
score: -100
Wrong Answer
time: 2ms
memory: 9956kb
input:
2 0 30959 840157 382961 250706 2 73638 750573 497639 377934
output:
497639
result:
wrong answer 1st lines differ - expected: '528598', found: '497639'