标签:cout bre nbsp span 循环 queue 无法 algorithm ext
超时,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; }
标签:cout bre nbsp span 循环 queue 无法 algorithm ext
原文地址:https://www.cnblogs.com/fzuhyj/p/10536605.html