1. 程式人生 > 實用技巧 >POJ1236 SCC縮點+DAG性質

POJ1236 SCC縮點+DAG性質

xg

題意

  N(2<N<100)各學校之間有單向的網路,每個學校得到一套軟體後,可以通過單向網路向周邊的學校傳輸,問題1:初始至少需要向多少個學校發放軟體,使得網路內所有的學校最終都能得到軟體。2,至少需要新增幾條傳輸線路(邊),使任意向一個學校發放軟體後,經過若干次傳送,網路內所有的學校最終都能得到軟體。

思路

  對於強連通分量,可以看作一個整體,然後進行縮點。

  至少提供多少個軟體,其實就是求入度為0的點的個數。

  若使得一個DAG成為強連通圖,實際就是零入度點的個數和零出度點的個數的最大值。所有都不需要建新圖。

  特判一下已經是強連通圖的情況。

  

#include <iostream>
#include 
<cmath> #include <cstdio> #include <cstring> #include <string> #include <map> #include <iomanip> #include <algorithm> #include <queue> #include <stack> #include <set> #include <vector> #define bug cout<<"--------------"<<endl #define
sp ' ' using namespace std; typedef long long ll; const int maxn = 1e5+10; int tot = 0; int head[maxn],ver[maxn],edge[maxn],nextt[maxn]; void add(int x,int y) { ver[++tot] = y,nextt[tot] = head[x] , head[x] = tot; } int dfn[maxn],low[maxn],sta[maxn],c[maxn],ins[maxn]; vector<int>scc[maxn];
int in[maxn],out[maxn]; int n,num,top,cnt; void tarjan(int x) { dfn[x]=low[x]=++num; sta[++top]=x,ins[x]=1; for(int i=head[x];i;i=nextt[i]) { int y=ver[i]; if(!dfn[y]){ tarjan(y); low[x]=min(low[x],low[y]); } else if(ins[y]){ low[x]=min(low[x],dfn[y]); } } if(dfn[x]==low[x]){ cnt++;int y; do{ y=sta[top--],ins[y]=0; c[y]=cnt,scc[cnt].push_back(y); }while(x!=y); } } int main() { //freopen("input.txt", "r", stdin); scanf("%d",&n); for(int i = 1;i <= n; ++i){ int y ; while(scanf("%d",&y)){ if(y == 0) break; add(i,y); } } for(int i =1 ;i <=n ;++i){ if(!dfn[i]) tarjan(i); } for(int x =1 ;x <=n ;++x){ for(int i =head[x] ;i;i = nextt[i]){ int y = ver[i]; if(c[x] == c[y]) continue; // addc(c[x],c[y]); in[c[y]]++; out[c[x]]++; } } //nub_edge = tc,nub_point = cnt; if(cnt == 1) { printf("1\n0"); return 0; } int innub = 0,outnub = 0; for(int i = 1;i <= cnt;++i){ if(!in[i]) innub++; if(!out[i]) outnub++; } printf("%d\n%d",innub,max(innub,outnub) ); }