题目连接:http://acm.pku.edu.cn/JudgeOnline/problem?id=2762
题目大意:是否存在任意u,v两点之间,有u——>v or v——>u;
解题思路:如果两点是在同一强连通分量里面,那么无论怎么样都能到达,如果两点不再同一强连通分量里面的话,只有这两个分量之间存在这样的路径就可以了,要求任意两个不再同一分量里面的点,只有他们存在与一条链上的时候才能满足条件。。。如果不在一条链上,那么必定存在至少2个点不能存在这样的路径。。。
所以解法:强连通分量+缩点+拓扑排序+DP(求最长链) 判断最长链是否等于强连通分量的个数。。。
代码:
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int MAX1=1010; const int MAX2=6010; struct Graph { int id,next; }; struct Edge { int s,e; }; Graph GA[MAX1+MAX2],GT[MAX1+MAX2]; Edge E[MAX2]; int visit[MAX1]; int order[MAX1]; int in[MAX1]; int out[MAX1]; int tp[MAX1]; int belong[MAX1]; int n,m,G_end,cnt,con; void init() { memset(GA,0, sizeof(GA)); memset(GT,0, sizeof(GT)); memset(in,0, sizeof(in)); memset(out,0,sizeof(out)); } void Bulid(int s,int e) { int p; p=s; while(GA[p].next) p=GA[p].next; GA[G_end].id=e; GA[p].next=G_end; p=e; while(GT[p].next) p=GT[p].next; GT[G_end].id=s; GT[p].next=G_end; G_end++; } void Bulid_again(int s,int e) { int p,q; p=s; while(GA[p].next) { q=GA[p].id; if(q==e) return ; p=GA[p].next; } GA[G_end].id=e; GA[p].next=G_end; G_end++; } void DFSA(int x) { visit[x]=1; int p,q; p=GA[x].next; while(p) { q=GA[p].id; if(!visit[q]) DFSA(q); p=GA[p].next; } order[cnt++]=x; } void DFST(int x) { visit[x]=1; int p,q; p=GT[x].next; while(p) { q=GT[p].id; if(!visit[q]) DFST(q); p=GT[p].next; } belong[x]=cnt; } void Topsort() { for(int i=0;i<cnt;i++) { if(in[i]==0) visit[i]=1; else visit[i]=0; } for(int i=0;i<cnt;i++) if(in[i]==0) { tp[con++]=i; in[i]=-1; } int fist=0; for(int k=1;k<=cnt;k++) { int p,q; p=GA[tp[fist++]].next; while(p) { q=GA[p].id; in[q]--; if(in[q]==0) { tp[con++]=q; if(visit[q]<1+visit[tp[fist-1]]) visit[q]=1+visit[tp[fist-1]]; in[q]=-1; } p=GA[p].next; } } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); G_end=n+1; int s,e; init(); for(int i=0;i<m;i++) { scanf("%d%d",&s,&e); E[i].s=s-1; E[i].e=e-1; Bulid(s-1,e-1); } cnt=0; memset(visit,0,sizeof(visit)); for(int i=0;i<n;i++) if(!visit[i]) DFSA(i); cnt=0; memset(visit,0,sizeof(visit)); for(int i=n-1;i>=0;i--) { if(!visit[order[i]]) { DFST(order[i]); cnt++; } } memset(GA,0,sizeof(GA)); G_end=cnt+1; for(int i=0;i<m;i++) { s=belong[E[i].s]; e=belong[E[i].e]; if(s!=e) { Bulid_again(s,e); in[e]++; out[s]++; } } con=0; Topsort(); int ans=0; for(int i=0;i<cnt;i++) if(ans<visit[i]) ans=visit[i]; if(ans==cnt) printf("Yes/n"); else printf("No/n"); } return 0; }