关于此题跑最短路会WA的疑问
查看原帖
关于此题跑最短路会WA的疑问
121813
老子是北瓜楼主2022/1/7 23:07

我的想法是连的边权是负的,然后spfa跑最短路(先不说会不会T)。将有关系的点看成连通块,对每个连通块分别加上一个数,使得每个连通块内求出来的解加上这个数大于等于1,为什么这样做会WA?

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#define N 100010 
using namespace std;

bool vis[N];
int ans[N],cnt[N],minn,res,n,k;
long long tot;
vector<pair<int,int> > g[N];
vector<int> g1[N];
queue<int> q;

void dfs(int u){
	tot+=ans[u]; ++res;
	minn=min(minn,ans[u]);
	for(int i=0; i<g1[u].size(); ++i)
	{
		int v=g1[u][i];
		if(vis[v]) continue;
		vis[v]=1;
		dfs(v);
	}
}

int qread(){
	int num=0; char ch=getchar();
	while(ch>'9' || ch<'0') ch=getchar();
	while(ch<='9' && ch>='0'){
		num=num*10+ch-'0';
		ch=getchar();
	}
	return num;
}

int main(){
	n=qread(); k=qread();
	for(int i=1; i<=n; ++i)
		g[0].push_back({i,0});
	while(k--){
		int opt,x,y;
		opt=qread(); x=qread(); y=qread();
		g1[x].push_back(y);
		g1[y].push_back(x);
		if(opt==1){
			g[x].push_back({y,0});
			g[y].push_back({x,0});
		}
		if(opt==2) g[y].push_back({x,-1}); 
		if(opt==3) g[x].push_back({y,0});
		if(opt==4) g[x].push_back({y,-1});
		if(opt==5) g[y].push_back({x,0});
	}
	
	memset(ans,0x3f,sizeof(ans));
	ans[0]=0; vis[0]=1;
	q.push(0);
	bool flag=1;
	
	while(!q.empty())
	{
		int u=q.front(); q.pop(); vis[u]=0;
		for(int i=g[u].size()-1; i>=0; --i)
		{
			int v=g[u][i].first,w=g[u][i].second;
			if(ans[u]+w<ans[v]){
				ans[v]=ans[u]+w;
				if(vis[v]==0){
					++cnt[v];
					vis[v]=1;
					q.push(v);
				}
				if(cnt[v]>n) {flag=0; break;}  
			}
		}
		if(flag==0) break;
	}
	
	if(flag)
	{
		memset(vis,0,sizeof(vis));
		for(int i=1; i<=n; ++i){
			if(vis[i]==0){
				minn=res=0;
				vis[i]=1;
				dfs(i);
				tot=tot-res*minn;
			}
		}
		cout<<tot+n;
	}
	else
		cout<<-1;
	return 0;
} 
2022/1/7 23:07
加载中...