n個學校之間有單向的網路,每個學校得到一套軟體後,可以通過單向網路向周邊的學校傳輸。
問題1:初始至少需要向多少個學校發放軟體,使得網路內所有的學校最終都能得到軟體。
問題2:至少需要新增幾條傳輸線路(邊),使任意向乙個學校發放軟體後,經過若干次傳送,網路內所有的學校最終都能得到軟體。
輸入有多組樣例,大約1000組。
每組樣例第一行包含兩個整數n,m(2<=n<=100),n代表學校的個數,m代表邊的個數(m每組樣例對應兩行,分別是問題一和問題二的解。
7 81 2
2 33 1
1 44 5
5 66 4
7 62
2分析,屬於同一強連通分量的學校可以共享軟體,所以可以將屬於同一強連通分量的學校看成乙個學校,這就是縮點,縮點後的有向圖是乙個有向無環圖,此時需要的軟體的個數就是入度為0的結點的數目。而要將所有點都連到乙個強連通分量內,簡單的想法就是使所有點的入度和出度都不為0.因此需新增的邊數就是入度和出度中的較大者(相當於從葉子到樹根連邊)。
需要注意的是,有一種特殊情況,那就是所有點本來就屬於同乙個強連通分量內。
2遍dfs
#include #include#define max(a,b) ((a)>(b)?(a):(b))
#define n 101
intg[n][n];
intn,m;
intans1,ans2;
intcnt;
intvis[n],dfn[n],id[n];
intdin[n],dout[n];
void dfs(int
u) dfn[cnt++]=u;
}void rdfs(intu)}
void
solve()
memset(vis,
0,sizeof
(vis));
cnt=0
;
for(t=n-1;t>=0;t--)
memset(din,
0,sizeof
(din));
memset(dout,
0,sizeof
(dout));
for(i=1;i<=n;i++)
}ans1=ans2=0
;
for(i=0;i)
if(cnt==1) printf("
1\n0\n");
else printf("
%d\n%d\n
",ans1,max(ans1,ans2));
}int
main()
solve();
}return0;
}
tarjan
#include #include#define min(a,b) ((a)
#define max(a,b) ((a)>(b)?(a):(b))
#define n 101
intg[n][n];
intn,m;
intcnt,num;
intdfn[n],low[n];
intstk[n],ins[n],top;
intid[n];
intdin[n],dout[n];
void dfs(int
u)
if(dfn[u]==low[u])
while(tmp!=u);
num++;
}}void
solve()
memset(din,
0,sizeof
(din));
memset(dout,
0,sizeof
(dout));
for(i=1;i<=n;i++)
}ans1=ans2=0
;
for(i=0;i)
if(num==1) printf("
1\n0\n");
else printf("
%d\n%d\n
",ans1,max(ans1,ans2));
}int
main()
solve();
}return0;
}
暑假集訓每日一題0717(DFS)
這題是zoj 1008那題。給你n n個方塊,每個方塊被對角線劃分為4部分,每一部分裡面有乙個數字,問能否將方塊拼成乙個邊長為n的大方塊,使得相鄰方塊的相鄰數字相同。用dfs搜尋,需要剪枝,同一層中相同方塊只搜尋一次。view code include include define n 26 def...
暑假集訓每日一題0712 (線段樹)
維護乙個只有0和1的整數序列,支援以下操作 1 x y v 將區間 x,y 之間的所有整數都變為v v為0或1 2 x y 將區間 x,y 之間所有的1變為0,所有的0變為1 3 x y 查詢區間 x,y 內的1的個數。線段數練習 每段儲存3個關鍵資訊 和,修改標記,反轉標記。需注意的幾點 在更新某...
暑假集訓每日一題0711 (線段樹)
維護乙個整數序列,支援以下操作 1 x v 將第x個整數的值修改為v 2 x y 查詢區間 x,y 之間的最小值 3 x y 查詢區間 x,y 之間的最大值 4 x y 查詢區間 x,y 內的整數和。資料保證查詢結果均在int範圍之內,但中間結果是否可能溢位呢?我交的程式沒考慮這個也ac了。通過這題...