日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

uva 558 Wormholes

發(fā)布時(shí)間:2025/3/20 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 uva 558 Wormholes 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

算是模板題,給定一個(gè)有向圖,頂點(diǎn)從0到n-1編號(hào),必須從0開始出發(fā),問(wèn)是否存在負(fù)環(huán)

一開始寫了一個(gè)Bellman-Ford,超時(shí),然后就放棄了,寫了個(gè)spfa的bfs版本,過(guò)了,然后又寫了一個(gè)spfa的dfs版本,wa,然后改了一個(gè)下午,還是wa

然后上網(wǎng)找了一下代碼,發(fā)現(xiàn)很多人寫的都是BF算法,看了一下自己的一樣,怎么會(huì)超時(shí)呢??

后來(lái)才發(fā)現(xiàn),我讀錯(cuò)題意了,我本來(lái)是理解為只要圖中有負(fù)環(huán)就好了,所有枚舉了所有的頂點(diǎn)作為源點(diǎn)去BF,所以才超時(shí),現(xiàn)在是規(guī)定了0作為源點(diǎn),所以就AC了

然后就把spfa的dfs版本改了一下,不要枚舉所有源點(diǎn),規(guī)定0為源點(diǎn),然后就AC了,再修改了一些細(xì)節(jié)地方,跑出了最好成績(jī)0.008排名第5

從這個(gè)地方可以看出,數(shù)據(jù)中,有的圖是不連通的,所以有的連通分量有負(fù)環(huán)有的沒有,如果枚舉了所以的源點(diǎn)的話,有可能會(huì)WA

?

但是有個(gè)地方比較困惑,我第一次寫spfa的bfs版本的時(shí)候也是枚舉了所有源點(diǎn)的,可以AC,照理來(lái)說(shuō)應(yīng)該是WA的,然后改為單源點(diǎn)后也是AC,是數(shù)據(jù)問(wèn)題??不可能啊

希望有人指點(diǎn)一下

?

下面給出代碼

?

Bellman-Ford

#include <cstdio> #include <cstring> #define N 1010 #define M 2010 #define INF 0x3f3f3f3f int d[N],u[M],v[M],w[M]; int n,m;int BF(int s) //Bellman-Ford {int k,i,j;for(i=0; i<n; i++) d[i]=INF;d[s]=0;for(k=1; k<n; k++) //進(jìn)行V-1次松弛for(int i=0; i<m; i++) //枚舉所有的邊 {int x=u[i],y=v[i];if( d[x]+w[i] < d[y] )d[y]=d[x]+w[i];}int OK=1;for(int i=0; i<m; i++) //檢查一遍所有的邊 {int x=u[i],y=v[i];if( d[x]+w[i] < d[y] ) //還能進(jìn)行松弛 {OK=0;break;}}return OK; } int main() {int T;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);for(int i=0; i<m; i++)scanf("%d%d%d",&u[i],&v[i],&w[i]);if(!BF(0)) //有負(fù)環(huán)printf("possible\n");elseprintf("not possible\n");}return 0; }

?

SPFA_BFS

#include <cstdio> #include <cstring> #include <queue> using namespace std; #define N 1010 #define NN 5 #define M 2010 #define INF 0x3f3f3f3f int n,m; int d[N],f[N],nnext[M],u[M],v[M],w[M]; //用數(shù)組來(lái)模擬鄰接表,并且使用頭插法 int c[N]; //記錄每個(gè)頂點(diǎn)進(jìn)隊(duì)的次數(shù) bool vis[N]; //標(biāo)記頂點(diǎn)在隊(duì)內(nèi)void input() {scanf("%d%d",&n,&m);memset(f,0,sizeof(f));//memset(nnext,0,sizeof(nnext));for(int i=1; i<=m; i++) //邊集數(shù)組從下標(biāo)1保存到m {scanf("%d%d%d",&u[i],&v[i],&w[i]);nnext[i]=f[u[i]]; //頭插法f[u[i]]=i; //頭插法 } /*printf("打印鄰接表:\n");for(int i=0; i<n; i++){printf("%d:\n",i);int j=f[i];while(j!=0){printf("%d %d\n",v[j],w[j]);j=nnext[j];}} */return ; }int spfa_bfs(int s) {queue <int> q;memset(d,0x3f,sizeof(d));d[s]=0;memset(c,0,sizeof(c));memset(vis,0,sizeof(vis));q.push(s); vis[s]=1; c[s]=1;//頂點(diǎn)入隊(duì)vis要做標(biāo)記,另外要統(tǒng)計(jì)頂點(diǎn)的入隊(duì)次數(shù)int OK=1;while(!q.empty()){int x;x=q.front(); q.pop(); vis[x]=0;//隊(duì)頭元素出隊(duì),并且消除標(biāo)記for(int k=f[x]; k!=0; k=nnext[k]) //遍歷頂點(diǎn)x的鄰接表 {int y=v[k];if( d[x]+w[k] < d[y]){d[y]=d[x]+w[k]; //松弛if(!vis[y]) //頂點(diǎn)y不在隊(duì)內(nèi) {vis[y]=1; //標(biāo)記c[y]++; //統(tǒng)計(jì)次數(shù)q.push(y); //入隊(duì)if(c[y]>NN) //超過(guò)入隊(duì)次數(shù)上限,說(shuō)明有負(fù)環(huán)return OK=0;}}}}return OK;} int main() {int T;scanf("%d",&T);while(T--){input();if(!spfa_bfs(0)) //有負(fù)環(huán)printf("possible\n");elseprintf("not possible\n");}return 0; }

?

SPFA_DFS

//時(shí)間最快0.008 #include <cstdio> #include <cstring> #define N 1010 #define M 2010 #define INF 0x3f3f3f3f int d[N],f[N]; bool vis[N]; struct edge {int u,v,w,next;}e[M]; int n,m;void input() {scanf("%d%d",&n,&m);memset(f,0,sizeof(f));for(int i=1; i<=m; i++) //讀入所有邊 {scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);int u=e[i].u;e[i].next=f[u];f[u]=i;} /*printf("打印鄰接表:\n");for(int i=0; i<n; i++){printf("%d:\n",i);for(int k=f[i]; k!=0; k=e[k].next)printf("%d %d\n",e[i].v,e[i].w);} */return ; }int spfa_dfs(int u) {vis[u]=1;for(int k=f[u]; k!=0; k=e[k].next){int v=e[k].v,w=e[k].w;if( d[u]+w < d[v] ){d[v]=d[u]+w;if(!vis[v]){if(spfa_dfs(v))return 1;}elsereturn 1;}}vis[u]=0;return 0; } int main() {int T;scanf("%d",&T);while(T--){input();for(int i=0; i<n; i++){ vis[i]=0; d[i]=INF;}d[0]=0;if(spfa_dfs(0)) printf("possible\n");else printf("not possible\n");}return 0; }

?

求指教 ?SPFA_BFS ?枚舉所有起點(diǎn),按道理應(yīng)該是WA的,為什么AC了…………

#include <cstdio> #include <cstring> #include <queue> using namespace std; #define N 1010 #define NN 5 #define M 2010 #define INF 0x3f3f3f3f int n,m; int d[N],f[N],nnext[M],u[M],v[M],w[M]; //用數(shù)組來(lái)模擬鄰接表,并且使用頭插法 int c[N]; //記錄每個(gè)頂點(diǎn)進(jìn)隊(duì)的次數(shù) bool vis[N]; //標(biāo)記頂點(diǎn)在隊(duì)內(nèi)void input() {scanf("%d%d",&n,&m);memset(f,0,sizeof(f));//memset(nnext,0,sizeof(nnext));for(int i=1; i<=m; i++) //邊集數(shù)組從下標(biāo)1保存到m {scanf("%d%d%d",&u[i],&v[i],&w[i]);nnext[i]=f[u[i]]; //頭插法f[u[i]]=i; //頭插法 } /*printf("打印鄰接表:\n");for(int i=0; i<n; i++){printf("%d:\n",i);int j=f[i];while(j!=0){printf("%d %d\n",v[j],w[j]);j=nnext[j];}} */return ; }int spfa_bfs(int s) {queue <int> q;memset(d,0x3f,sizeof(d));d[s]=0;memset(c,0,sizeof(c));memset(vis,0,sizeof(vis));q.push(s); vis[s]=1; c[s]=1;//頂點(diǎn)入隊(duì)vis要做標(biāo)記,另外要統(tǒng)計(jì)頂點(diǎn)的入隊(duì)次數(shù)int OK=1;while(!q.empty()){int x;x=q.front(); q.pop(); vis[x]=0;//隊(duì)頭元素出隊(duì),并且消除標(biāo)記for(int k=f[x]; k!=0; k=nnext[k]) //遍歷頂點(diǎn)x的鄰接表 {int y=v[k];if( d[x]+w[k] < d[y]){d[y]=d[x]+w[k]; //松弛if(!vis[y]) //頂點(diǎn)y不在隊(duì)內(nèi) {vis[y]=1; //標(biāo)記c[y]++; //統(tǒng)計(jì)次數(shù)q.push(y); //入隊(duì)if(c[y]>NN) //超過(guò)入隊(duì)次數(shù)上限,說(shuō)明有負(fù)環(huán)return OK=0;}}}}return OK;} int main() {int T;scanf("%d",&T);while(T--){input();int s;for(s=0; s<n; s++) //枚舉所有源點(diǎn) {int tmp=spfa_bfs(s) ;//for(int i=0; i<n; i++)//printf("%d ",d[i]);//printf("\n");if(!tmp) break;}if(s<n) //有負(fù)環(huán)printf("possible\n");elseprintf("not possible\n");}return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/scau20110726/archive/2012/11/24/2786249.html

總結(jié)

以上是生活随笔為你收集整理的uva 558 Wormholes的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。