標籤:檔案 getc 加強 blank using nod 思路 cow poj1236
P2746 [USACO5.3]校園網Network of Schools// POJ1236: Network of Schools題目描述
一些學校連入一個電腦網路。那些學校已訂立了協議:每個學校都會給其它的一些學校分發軟體(稱作“接受學校”)。注意即使 B 在 A 學校的分發列表中, A 也不一定在 B 學校的列表中。
你要寫一個程式計算,根據協議,為了讓網路中所有的學校都用上新軟體,必須接受新軟體副本的最少學校數目(子任務 A)。更進一步,我們想要確定通過給任意一個學校發送新軟體,這個軟體就會分發到網路中的所有學校。為了完成這個任務,我們可能必須擴充接收學校列表,使其加入新成員。計算最少需要增加幾個擴充,使得不論我們給哪個學校發送新軟體,它都會到達其餘所有的學校(子任務 B)。一個擴充就是在一個學校的接收學校列表中引入一個新成員。
輸入輸出格式
輸入格式:
輸入檔案的第一行包括一個整數 N:網路中的學校數目(2 <= N <= 100)。學校用前 N 個正整數標識。
接下來 N 行中每行都表示一個接收學校列表(分發列表)。第 i+1 行包括學校 i 的接收學校的標識符。每個列表用 0 結束。空列表只用一個 0 表示。
輸出格式:
你的程式應該在輸出檔案中輸出兩行。
第一行應該包括一個正整數:子任務 A 的解。
第二行應該包括子任務 B 的解。
輸入輸出範例
輸入範例#1: 複製
52 4 3 04 5 0001 0
輸出範例#1: 複製
12
說明
題目翻譯來自NOCOW。
USACO Training Section 5.3
解題報告:題目大意:給定一個有向圖,求1.至少要選幾個點,可以到達全部的點,2.至少要連幾條邊,使得整個圖是強聯通的(即從任意一個頂點出發,可以到達任意一個頂點)有用的定理:有向非循環圖中所有入度不為0的點,一定可以由某個入度為0的點出發可達。 (由於無環,所以從任何入度不為0的點往回走,必然終止於一個入度為0的點)思路:tarjan縮點,求出入度為0的點的個數,即為1的答案;在DAG上要加幾條邊,才能使得DAG變成強連通的,問題2的答案就是多少,加邊的方法:要為每個入度為0的點添加入邊,為每個出度為0的點添加出邊假定有 n 個入度為0的點,m個出度為0的點, max(m,n)就是第二個問題的解(證明難,略)
#include<iostream>#include<queue>#include<cstdio>#include<cstring>#include<algorithm>#include<stack>#include<vector>#define N 2000000using namespace std;void in(int &x){ register char c=getchar();x=0;int f=1; while(!isdigit(c)){if(c==‘-‘) f=-1;c=getchar();} while(isdigit(c)){x=x*10+c-‘0‘;c=getchar();} x*=f;}int ans1,ans2,n,tot,head[N];struct node{ int to,next;}e[N];int dfn[N],low[N],cnt,item,belong[N],rd[N],cd[N];stack<int>S;bool vis[N];void tarjan(int u){ dfn[u]=low[u]=++item; vis[u]=1;S.push(u); for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); }else if(vis[v]) low[u]=min(low[u],dfn[v]); }if(low[u]==dfn[u]){ int v=u;++cnt; do{ v=S.top();S.pop(); vis[v]=0;belong[v]=cnt; }while(v!=u); }}void add(int u,int v){ e[++tot].to=v,e[tot].next=head[u],head[u]=tot;}int main(){ in(n); for(int x,i=1;i<=n;i++){ while(1){ in(x); if(!x) break; add(i,x); } }for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++){ for(int j=head[i];j;j=e[j].next){ int v=e[j].to; if(belong[i]!=belong[v]){ rd[belong[v]]++; cd[belong[i]]++; } } }for(int i=1;i<=cnt;i++){ if(!rd[i]) ++ans1; if(!cd[i]) ++ans2; }ans2=max(ans1,ans2); if(cnt==1) ans2=0; printf("%d\n%d",ans1,ans2); return 0;}
洛穀P2812是這題的加強版,可以順便A掉
P2746 [USACO5.3]校園網Network of Schools// POJ1236: Network of Schools