首页 > 代码库 > UVALive 6195 The Dueling Philosophers Problem 强连通缩点+拓扑序
UVALive 6195 The Dueling Philosophers Problem 强连通缩点+拓扑序
题目链接:点击打开链接
给定n个点m条限制
下面限制 u->v
表示u必须排在v前面,问把n个数排成一排有多少种方法。
若有0种输出0
1种输出1
多种输出2
**边的数量题目里少了个0==
思路:
0种就是有环,缩点一下判断强连通分量是不是n个。
1种就是拓扑序时队列里任何时刻都只有一个点
否则就是2种
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include <queue> #include<cmath> #include<iostream> #include<algorithm> #include<vector> using namespace std; const int N = 1000000; const int M = 1000010; struct Edge{ int from, to, nex; }edge[M]; int head[N], edgenum; void add(int u, int v){ Edge E = {u,v,head[u]}; edge[edgenum] = E; head[u] = edgenum++; } int DFN[N], Low[N], Stack[N], top, Time; int taj; bool Instack[N]; void tarjan(int u, int fa){ DFN[u] = Low[u] = ++Time; Stack[top++] = u; Instack[u] = 1; for(int i = head[u]; ~i; i = edge[i].nex){ int v = edge[i].to; if(DFN[v] == -1) { tarjan(v, u); Low[u] = min(Low[u], Low[v]); } else if(Instack[v])Low[u] = min(Low[u], DFN[v]); } if(Low[u] == DFN[u]) { int now ; taj++; do{ now = Stack[--top]; Instack[now] = 0; }while(now != u); } } void tarjan_init(int all){ for(int i = 1; i <= all; i++) { DFN[i] = -1; Instack[i] = 0; } top = Time = taj = 0; for(int i = 1; i <= all; i++) if(DFN[i] == -1) tarjan(i, i); } int in[N]; void suodian(){ for(int i = 1; i <= taj; i++) in[i] = 0; for(int i= 0; i < edgenum; i++) in[edge[i].to]++; } void init(){memset(head, -1, sizeof head); edgenum = 0;} int n, m; int topsort(int x){ queue<int> q; q.push(x); int inque = 0; while(!q.empty()){ int u = q.front(); q.pop(); inque ++; for(int i = head[u]; ~i; i = edge[i].nex){ int v = edge[i].to; in[v]--; if(in[v] == 0) q.push(v); } if((int)q.size() > 1) return 2; } if(inque != n) return 2; return 1; } int work(){ tarjan_init(n); if(taj != n)return 0; suodian(); int ru = -1; for(int i = 1; i <= n; i++) if(in[i] == 0) { if(ru == -1) ru = i; else return 2; } if(ru == -1) return 0; return topsort(ru); } void input(){ init(); // if(n>=N||n<1||m>=M||m<1)while(1); while(m--){ int u, v; scanf("%d %d", &u, &v); if(u<1||u>n||v<1||v>n||u==v)continue; add(u, v); } } int main(){ while(cin>>n>>m, n+m){ input(); cout<<work()<<endl; } return 0; } /* 5 4 1 5 5 2 3 2 4 3 5 4 3 1 4 2 1 5 5 4 2 2 1 2 2 1 4 4 1 2 2 3 3 4 4 1 1 0 0 0 */
UVALive 6195 The Dueling Philosophers Problem 强连通缩点+拓扑序
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。