(图爆了,重新交一次)
本题我用了dfs与bfs两种解法,但#9显然是在卡dfs,所以遗憾91分。代码附于文末,可供参考。
当bfs中一个点的d值被更新达到n次,说明图中存在负环。
如下图
如果是bfs求最短路的话,势必会在这个环里无限转圈。所以我们用一个下标对应点编号的数组来存这个点被访问的次数
因为一个点最多与n-1个点相连,也就是最多被访问n-1次。所以当这个点被访问到n次时,这条路径上一定有负环。
代码如下
#include<bits/stdc++.h>
using namespace std;
const int N=10005;//好看
int t,n,m,u,v,w,biss[N],b[N],p[N][N],d[N],flag=0;//flag用于判是否已经判了有负环。如果flag被更新,就输出“NO”
struct lyf {
int v,w;
lyf(int a,int b) {
v=a;
w=b;
}
};
vector<lyf> g[N];
bool bis[N];
queue<int> q;//队列做bfs
int main() {
cin>>t;
for(int o=1;o<=t;o++) {
cin>>n>>m;
memset(d,0x7f,sizeof(d));
memset(b,0,sizeof(b));
flag=0;//初始化
for(int i=1; i<=m; i++) {
cin>>u>>v>>w;
g[u].push_back(lyf(v,w));
if(w>=0)g[v].push_back(lyf(u,w));//一定注意!!①题意是非负边双向②注意是非负边!!#9里有个w就是0!
}
d[1]=0;
q.push(1);//题意,从1开始
while(!q.empty()) {
u=q.front();
q.pop();
bis[u]=0;
if(b[u]>=n) {
cout<<"YES"<<endl;
flag=1;
break;
}
for(int i=0; i<g[u].size(); i++)if(d[u]+g[u][i].w<d[g[u][i].v]) {
b[g[u][i].v]++;
d[g[u][i].v]=d[u]+g[u][i].w;
if(!bis[g[u][i].v]) {
bis[g[u][i].v]=1;
q.push(g[u][i].v);
}
}
}
for(int i=1; i<=n; i++)
g[i].clear();//清空。不然。。。。。
if(!flag)
cout<<"NO"<<endl;
}
return 0;
}
dfs则是通过判断有没有重复访问一个相同的点,通过两个bool数组实现。
代码附于下
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int d[N],a,e,c,t,n,m;
struct ljh {
int v,w;
ljh(int v,int w):v(v),w(w) {}
};
vector <ljh> g[N];
bool flag,vis[N],b[N];
void dfs(int k) {
if (flag)
return;
vis[k]=true;
for (int i=0; i<g[k].size(); ++i)
if (d[k]+g[k][i].w<d[g[k][i].v]) {
if (vis[g[k][i].v]) {
flag=true;
return;
}
d[g[k][i].v]=d[k]+g[k][i].w;
dfs(g[k][i].v);
}
vis[k]=false;
}
void lyf(int u) {//遍历1能到的点,也是dfs
for(int i=0; i<g[u].size(); i++) {
if(g[u][i].w&&!b[g[u][i].v]) {
b[g[u][i].v]=1;
lyf(g[u][i].v);
}
}
}
int main() {
cin>>t;
for(int i=1; i<=t; i++) {
cin>>n>>m;
for(int j=1; j<=m; j++) {
cin>>a>>e>>c;
g[a].push_back(ljh(e,c));
if(c>=0)
{
g[e].push_back(ljh(a,c));
}
}
memset(d,0x7f,sizeof(d));
memset(b,0,sizeof(b));//不对正边扩展,剪枝
memset(vis,0,sizeof(vis));
flag=false;
lyf(1);
b[1]=1;
for (int i=1; i<=n && !flag; ++i)
if(b[i]==1)
dfs(i);
if(flag==0) {
cout<<"NO"<<endl;
} else {
cout<<"YES"<<endl;
}
for(int i=1;i<=n;i++)
{
g[i].clear();
}
}
return 0;
}
如果能用dfs改出来的大佬,私我,让傻孩子见见世面。。