1 solutions
-
0
难度: 绿
算法: 强连通分量,缩点
首先对于两只牛 ,如果 喜欢 ,则连一条自 向 的有向边,然后在这个图上跑强连通分量并缩点,得到有向无环图。
在这里证明一个东西:
一个有向无环图至少有一个节点出度为 。
使用反证,如果没有点出度为 :
对于第 个点,其至少有一条边连向别的点,不妨设其连向了第 个点。
对于第 个点,其同样至少有一条边连向别的点,但不能连向第 个点,不妨设其连向了第 个点。
对于第 个点,其仍然至少有一条边连向别的点,但不能连向第 个点,不妨设其连向了第 个点。
......以此类推,那么最后一个点不能连向所有的点,矛盾。所以原命题得证。
如果有恰好一个点出度为 ,那么答案就是这个点的大小。因为其他的点上的牛都不被这个点上的牛所喜欢。而由于其他点都有出度,所以必定都喜欢这个点上的牛。
如果有多于一个点出度为 ,那么答案就为 ,因为这两个节点上的牛互相不喜欢。
代码如下:
#include<bits/stdc++.h> using namespace std; int n,m,a,b,u; int l[10010],d[10010],in[10010],s[10010],c,t,p[10010],sz[10010]; stack<int> st; vector<int> e[10010],k[10010]; void tarj(int u){ l[u]=d[u]=++c; st.push(u); in[u]=1; for(int i=0;i<int(e[u].size());i++){ int v=e[u][i]; if(!d[v]){ tarj(v); l[u]=min(l[u],l[v]); } else if(in[v]){ l[u]=min(l[u],l[v]); } } if(l[u]==d[u]){ t++; while(1){ sz[t]++; s[st.top()]=t; in[st.top()]=0; if(st.top()==u){ st.pop(); break; } st.pop(); } } } int main(){ ios::sync_with_stdio(0); cin>>n>>m; for(int i=1;i<=m;i++){ cin>>a>>b; e[a].push_back(b); } for(int i=1;i<=n;i++){ if(!d[i]) tarj(i); } for(int i=1;i<=n;i++){ for(int j=0;j<int(e[i].size());j++){ if(s[i]!=s[e[i][j]]) k[s[i]].push_back(s[e[i][j]]); } } for(int i=1;i<=t;i++){ if(k[i].empty()) u++; } if(u>1){ cout<<0; return 0; } for(int i=1;i<=t;i++){ if(k[i].empty()){ cout<<sz[i]; return 0; } } }
- 1
Information
- ID
- 93
- Time
- 1000ms
- Memory
- 512MiB
- Difficulty
- 8
- Tags
- # Submissions
- 12
- Accepted
- 9
- Uploaded By