QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#292612#1295. Fastest Speedrunsnow_traceWA 2ms9956kbC++142.5kb2023-12-28 09:34:362023-12-28 09:34:37

Judging History

你现在查看的是最新测评结果

  • [2023-12-28 09:34:37]
  • 评测
  • 测评结果:WA
  • 用时:2ms
  • 内存:9956kb
  • [2023-12-28 09:34:36]
  • 提交

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'