通信網絡
阿新 • • 發佈:2019-03-15
正常的 循環 return false 反向連接 但是 tac 鄰接表 tor
超時,60
#include<cstdio> #include<iostream> #include<algorithm> #include<vector> #include<string> #include<queue> #include<map> #include<stack> using namespace std; const int maxn = 10005 ; int d[1005][1005]; //d[i][j]=1 表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識//d[i][j]=2 表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門 bool vis[1005]; //vis[i]=true 表示具有所有d[x][i]=1的部門 int main() { int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { vis[i] = false; for(int j=1;j<=n;j++) { if(i!=j) d[i][j] = 0; else d[i][j] = 1; } } for(int i=1;i<=m;i++) { int u,v; scanf("%d %d",&u,&v); d[u][v] = 1; //d[i][j]=1 表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識 ,可傳遞 d[v][u] = 2; //d[i][j]=2 表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門 ,不可傳遞} for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { if(d[k][i]==1 && i!=k) { queue<int> q; q.push(k); while(!q.empty()) { int temp = q.front(); q.pop(); for(int j=1;j<=n;j++) { if(d[j][temp] == 1 && j!=temp) { d[j][i] = 1; if(d[i][j]!=1) d[i][j] = 2; if(vis[j] == false) { vis[j] = true; q.push(j); } } } } } } } int ans = 0,i,j; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(d[i][j] == 0) break; } if(j==n+1) ans++; } cout<<ans; return 0; }
超時,80
#include<cstdio> #include<iostream> #include<algorithm> #include<vector> #include<string> #include<queue> #include<map> #include<stack> using namespace std; const int maxn = 10005 ; int d[1005][1005]; //d[i][j]=1 表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識 //d[i][j]=2 表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門 bool vis[1005]; //vis[i]=true 表示具有所有d[x][i]=1的部門 bool used[1005]; struct EDGE { int u,v; }e[10005]; //節省時間,不必通過2個for循環尋找d[i][j]=1的邊 //通過e數組和vis 節省時間 int main() { int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { vis[i] = false; for(int j=1;j<=n;j++) { if(i!=j) d[i][j] = 0; else d[i][j] = 1; } } for(int i=1;i<=m;i++) { scanf("%d %d",&e[i].u,&e[i].v); d[e[i].u][e[i].v] = 1; //d[i][j]=1 表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識 ,可傳遞 d[e[i].v][e[i].u] = 2; //d[i][j]=2 表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門 ,不可傳遞 } int u,v; for(int k=1;k<=m;k++) { u = e[k].u; v = e[k].v; if(vis[u] == true) //說明所有d[x][u]=1的點都已經找到,不需要回溯 { for(int j=1;j<=n;j++) { if(d[j][u] == 1 && j!=u) { d[j][v] = 1; if(d[v][j]!=1) d[v][j] = 2; } } continue; } for(int j=1;j<=n;j++) used[j]=false; //false表示此次回溯中還沒用過的點,防止雙向回路死循環(用dfs,bfs特別註意), queue<int> q; //v向前回溯,尋找所有d[x][v]=1的點, q.push(v); //先尋找所有d[x][v]=1的點,再逐級往前推,bfs used[v] = true; while(!q.empty()) //錯誤點:死循環,有雙向回路的時候 { int temp = q.front(); //第一次是v,第二次是使d[x][v]=1的x q.pop(); for(int j=1;j<=n;j++) { if(d[j][temp] == 1 && j!=temp) { d[j][v] = 1; if(d[v][j]!=1) d[v][j] = 2; if(vis[temp] == true) //說明所有d[x][temp]=1的點都已經找到,隊列不需要繼續添加temp前面的j continue; if(used[j] == true) //頂點j已經參與回溯過 continue; q.push(j); used[j] = true; } } } vis[v] = true; //通過回溯具有了所有d[x][v]=1的信息,x不一定與v直接連接 } int ans = 0,i,j; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(d[i][j] == 0) break; } if(j==n+1) ans++; } cout<<ans; return 0; }
編譯錯誤
#include<cstdio> #include<iostream> #include<algorithm> #include<vector> #include<string> #include<queue> #include<map> #include<stack> using namespace std; int first[10005],next[10005]; int d[1005][1005]; //d[i][j]=1 表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識 , //d[i][j]=2 表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門 bool vis[1005]; //vis[i]=true 表示具有所有d[x][i]=1的部門 bool used[1005]; struct EDGE { int u,v; }e[10005]; //通過e數組節省時間,不必通過2個for循環尋找d[i][j]=1的邊 //通過vis數組節省時間,不必重復回溯 //通過鄰接表節省時間,u已知, 不必通過循環找到所有d[x][u]=1的點, 通過鄰接表(反向連接) int main() { int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { vis[i] = false; for(int j=1;j<=n;j++) { if(i!=j) d[i][j] = 0; else d[i][j] = 1; } } for(int i=1;i<=m;i++) { first[i] = -1; next[i] = -1; } for(int i=1;i<=m;i++) { scanf("%d %d",&e[i].u,&e[i].v); d[e[i].u][e[i].v] = 1; //d[i][j]=1 表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識 ,可傳遞 d[e[i].v][e[i].u] = 2; //d[i][j]=2 表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門 ,不可傳遞 next[i] = first[e[i].v]; //反向連接 ,2->1,3->1,e數組存儲的還是正常的路徑順序,u=2,v=1 ;u=3,v=1 first[e[i].v] = i; //但是通過鄰接表連起來的順序是 1->2->3, } /* for(int i=1;i<=n;i++) { int num = first[i]; while(num!=-1) { cout<<e[num].u<<" "<<e[num].v<<endl; num = next[num]; } cout<<endl; }*/ int u,v,j; for(int k=1;k<=m;k++) { u = e[k].u; v = e[k].v; if(vis[u] == true) //說明所有d[x][u]=1的點都已經找到,不需要回溯,只需要使所有d[x][v]=1 { j = first[u]; //每個e[j]都是類似 x->->->u 這樣的邊 while(j!=-1) { d[e[j].u][v] = 1; if(d[v][e[j].u]!=1) d[v][e[j].u] = 2; j = next[j]; } continue; } for(j=1;j<=n;j++) used[j]=false; //false表示此次回溯中還沒用過的點,防止雙向回路死循環(用dfs,bfs特別註意), queue<int> q; q.push(v); //尋找所有d[x][v]=1的點,x------>v used[v] = true; //編號為v的頂點已經使用 while(!q.empty()) //錯誤點:死循環,有雙向回路的時候 { int temp = q.front(); q.pop(); j = first[temp]; while(j!=-1) { //找到所有d[x][temp]=1的點,令d[x][v] = 1; //每個e[j] 都是 x->->temp 的邊, d[e[j].u][v] = 1; if(d[v][e[j].u]!=1) d[v][e[j].u] = 2; if(vis[temp] == true) //說明所有d[x][temp]=1的點都已經找到,隊列不需要繼續添加temp前面的j { j = next[j]; continue; } if(used[e[j].u] == true) //頂點e[j].u已經使用過 { j = next[j]; continue; } q.push(e[j].u); used[e[j].u] = true; j = next[j]; } } vis[v] = true; //通過回溯具有了所有d[x][v]=1的信息,x不一定與v直接連接 } int ans = 0,i; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(d[i][j] == 0) break; } if(j==n+1) ans++; } cout<<ans; return 0; }
通信網絡