AcWing 401.从u到v还是从v到u?
出自POJ2762:Going from u to v or from v to u?
给定一个 n 个点 m 条边的有向图,现在要求图中任意两点 u 和 v,均可满足 u 能通往 v 或 v 能通往 u,请你判断要求是否能够成立。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组测试数据,第一行包含两个整数 n 和 m。
接下来 m 行,每行包含两个整数 u 和 v,表示点 u 和点 v 之间存在一条有向边。
输出格式
每组数据输出一个结果,如果要求成立,则输出 Yes,否则输出 No。
数据范围
0<n<1001,m<6000。
样例
输入:
1
3 3
1 2
2 3
3 1
输出样例:
Yes
思路:
题意:
∀
(
u
→
v
)
a
n
d
(
v
↛
u
)
{\forall} (u \rightarrow v)and(v\nrightarrow u)
∀(u→v)and(v↛u)
先看看样例,如图:
①可以到②,间接到③
……
如果题意是u->v且v->u,那么很显然就是构成一个强连通分量。
然而这道题是 “或”,有点难想了。
那么不妨反过来想:如果不能(输出No)是怎样的情况?
即
∃
(
(
u
↛
v
)
a
n
d
(
v
↛
u
)
)
{\exists} (( u\nrightarrow v) and (v\nrightarrow u))
∃((u↛v)and(v↛u))
这是存在啊,那意味着什么呢?找到一个特例即可。
即存在两个点,两者不能互相能到达。
这么想,可以统计每个点的出度和入度。
如果各点出度为0的个数和各点入度为0的个数的最大值大于2时No,否则Yes。
即存在两个点的入度都为0或两个点出度都为0时No,否则Yes。
是不是很离谱?!就这,就YES?NO?了
证明一下就理解了:
反证法:
显然②、③的入度(出度)为0,他们无法到达。
code:
#include<bits/stdc++.h>
using namespace std;
int n,m,chu[1001], ru[1001];
int main(){
cin>>n;
while(cin>>n>>m){
int ans=0, res=0;
for(int i=0;i<=1000;i++)chu[i]=ru[i]=0;
for(int i=1,x,y;i<=m;i++){
cin>>x>>y; chu[x]++,ru[y]++;
}
for(int i=1;i<=n;i++){
if(!chu[i]) ans++; if(!ru[i]) res++;
}
if(max(ans,res)<=1) cout<<"Yes\n"; else cout<<"No\n";
}
}
就这样解决了别人一二百行的代码!代码思路来自大佬lky 快来Orz。