题目链接:点击打开链接
给定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
*/