poj1236(强连通分量)

来源:互联网 发布:新浪短链接数据分析 编辑:程序博客网 时间:2024/05/16 05:13

POJ1236
一些学校通过网络连接在一起,每个学校手中
有一份名单,即它所指向的点。学校A的名单中
有学校B,并不能保证学校B的名单里有学校A。
现在有一软件。
1.问至少发给几个学校才能保证所有的学校都可
以得到该软件。
2.至少加几条边才能使将软件发给任何一个学校
后,其他所有学校都可以得到软件。
N<=100000

 

第一个是求缩点后,入度为0的点数;

第二问是求max(入度为0数,出度为0数);

 

有坑就是当数据只有一个scc时,第二问答案是0,不是1!!

 

#include<cstdio>#include<cmath>#include<stack>#include<cstdlib>#include<algorithm>using namespace std;const int N=50005;int n,m;int head[N],tot,to[N],pre[N];void addedge(int x,int y){to[++tot]=y;pre[tot]=head[x];head[x]=tot;}int dfn[N],low[N],id,in[N],out[N],pos[N],size;bool sta[N];stack<int> s;void dfs(int u){dfn[u]=low[u]=++id;s.push(u);sta[u]=true;for (int i=head[u];i;i=pre[i])if (!dfn[to[i]]){dfs(to[i]);low[u]=min(low[u],low[to[i]]);}else if (sta[to[i]]) low[u]=min(low[u],dfn[to[i]]);if (low[u]==dfn[u]){size++;int x;do{x=s.top();s.pop();pos[x]=size;sta[x]=false;}while (x!=u);}}int main(){scanf("%d",&n);for (int i=1;i<=n;i++){int x;do {scanf("%d",&x);if (x!=0) addedge(i,x);}while (x);}for (int i=1;i<=n;i++) if (!dfn[i]) dfs(i);for (int u=1;u<=n;u++)for (int i=head[u];i;i=pre[i]){int v=to[i];if (pos[u]!=pos[v]){out[pos[u]]=1;in[pos[v]]=1;}}int ans1=0,ans2=0;for (int i=1;i<=size;i++) ans1+=1-in[i];for (int i=1;i<=size;i++) ans2+=1-out[i];ans2=max(ans1,ans2);if (size==1) ans2=0;printf("%d\n%d",ans1,ans2);return 0;} 

总结:

注意特判:有的时候当抽象出了数学模型后,找到一个做法,但根据实际问题,我们还是需要特判最小或者边界的情况,才行,毕竟有的时候模型不能概括出所有的情况。

0 0