poj 1236 Network of Schools
http://poj.org/problem?id=1236
题意:1.要求出至少发分配多少站点,使所有点都能收到,即求入度为0的分量。
2.求要添加多少点,使任意一个点发送物品,其他点都能收到物品,即求Max(入度为0的分量个数,出度为0的分量个数)。
注意单点的情况.

#include<string.h> #include<stdio.h> #include<iostream> #include<stack> #include<utility> using namespace std; const int maxn = 105; struct nd { int u,v,next; }edge[maxn*100]; int head[maxn],ecnt,idx,cnt; int dfn[maxn],low[maxn],vis[maxn],in[maxn],out[maxn],belong[maxn]; stack<int>st; void add(int u,int v) { edge[ecnt].u = u; edge[ecnt].v = v; edge[ecnt].next = head[u]; head[u] = ecnt++; } void tarjan(int u) { int i,v; dfn[u] = low[u] = ++idx; st.push(u); vis[u] = 1; for(i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if(!dfn[v]){ tarjan(v); low[u] = min(low[v],low[u]); }else if(vis[v]) low[u] = min(dfn[v],low[u]); } if(dfn[u]==low[u]){ cnt++; do{ v = st.top(); st.pop(); vis[v] = 0; belong[v] = cnt; }while(v!=u); } } int main() { int i,j,k,t,n,u,v; while(scanf("%d",&n)==1) { memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(belong,0,sizeof(belong)); ecnt = 0; idx = 0; cnt=0; for(i = 1; i <= n; ++ i) while(scanf("%d",&v)&&v) add(i,v); for(i = 1; i <= n; ++ i) if(!dfn[i])tarjan(i); int c1 = 0,c2 = 0; for(i = 0; i < ecnt; ++ i) { u = edge[i].u; v = edge[i].v; u = belong[u]; v = belong[v]; if(u!=v){ in[v] = 1; out[u] = 1; } } for(i = 1; i <= cnt; ++ i){ if(!in[i])c1++; if(!out[i])c2++; } if(cnt==1){puts("1\n0"); continue;} printf("%d\n%d\n",c1,max(c1,c2)); } return 0; }