下面允許我偷個懶,洛谷上寫過的blog我就不來再抄一遍了c++
那麼我先講一講今天晚上的第一道題吧(話說今天晚上好黑教室裏還就我一個銀_ (:з」∠)_)!
題目以下:git
There are exactly nn towns in Byteotia.安全
Some towns are connected by bidirectional roads.app
There are no crossroads outside towns, though there may be bridges, tunnels and flyovers. Each pair of towns may be connected by at most one direct road. One can get from any town to any other-directly or indirectly.ide
Each town has exactly one citizen.函數
For that reason the citizens suffer from loneliness.大數據
It turns out that each citizen would like to pay a visit to every other citizen (in his host’s hometown), and do it exactly once. So exactly n\cdot (n-1)n⋅(n−1) visits should take place.ui
That’s right, should.this
Unfortunately, a general strike of programmers, who demand an emergency purchase of software, is under way.spa
As an act of protest, the programmers plan to block one town of Byteotia, preventing entering it, leaving it, and even passing through.
As we speak, they are debating which town to choose so that the consequences are most severe.
Task Write a programme that:
reads the Byteotian road system’s description from the standard input, for each town determines, how many visits could take place if this town were not blocked by programmers, writes out the outcome to the standard output.
給定一張無向圖,求每一個點被封鎖以後有多少個有序點對(x,y)(x!=y,1<=x,y<=n)知足x沒法到達y
(不貼了,反正一堆英文你懂得)
輸入樣例#1:
5 5
1 2
2 3
1 3
3 4
4 5
輸出樣例#1:
8
8
16
14
8
話說翻譯講的好模糊啊我看着道題看了半天就是看不出來那個答案是怎麼來的。。。
好吧我再好好講講:這道題就是說給你n個點和m條無向邊,讓你分別求:第i個點所連的邊都被切掉的時候有多少對點是沒法相互到達的(注意1 ,2 和 2 , 1是不一樣的一對點,也能夠理解爲最終求出的點對要*2),也就是說第i個點也是要算在沒法相互到達的點對以內的。另外注意題目給出的圖是個無向連通圖。完了我也不想贅述了,題意也就差很少是這樣,tarjan縮縮點差很少能夠水過去。
此外,本題與割點相關
#include<bits/stdc++.h>
#define M 110000
typedef long long ll;
using namespace std;
inline ll read() //平常讀優(最近tarjan一堆大數據搞得我很焦躁什麼數據類型都用longlong了)
{
ll x=0; char c=getchar();
while(!isdigit(c)) c=getchar();
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x;
}
ll n,m,tim,pat=1;
ll size[M],f[M];
ll dfn[M],low[M];
ll head[M],ans[M];
struct Edge{ int v,next; }e[M*10];
void add(int u,int v) { e[pat].next=head[u]; e[pat].v=v; head[u]=pat++; }
void tarjan(int u) //tarjan(相較模板有改動,由於要求割點。PS:本題和割點也有關)
{
int ape=1,chd=0;
++size[u]; ans[u]+=n-1;
dfn[u]=low[u]=++tim;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].v; if(f[u]==v) continue;
if(!dfn[v])
{
f[v]=u; tarjan(v); size[u]+=size[v]; ++chd; low[u]=min(low[u] , low[v]);
if(u!=1 && dfn[u]<=low[v]) ape+=size[v], ans[u]+=(n-ape)*size[v];
//是割點,appear加上該子樹的size,ans加上未出現的節點數(n-appear)*(該子樹的大小)size
}
else low[u]=min(low[u] , dfn[v]);
}
if(u==1 && chd>=2) //單獨判斷根節點u是不是割點,是的話就進行累加
for(int i=head[u];i;i=e[i].next) if(f[e[i].v]==u)
for(int j=e[i].next;j;j=e[j].next) if(f[e[j].v]==u)
ans[u]+=size[e[i].v]*size[e[j].v]; //這裏是直接子樹大小 * 子樹大小了
}
int main()
{
n=read(); m=read();
for(int i=1;i<=m;++i) //讀邊不解釋
{ int u=read(),v=read(); add(u,v); add(v,u); }
tarjan(1); //該圖自己聯通,只需從點1出發便可
for(int i=1;i<=n;++i) //tarjan中已經處理完了答案,直接輸出便可
printf("%lld\n",ans[i]<<1);
return 0;
}
煤礦工地能夠當作是由隧道鏈接挖煤點組成的無向圖。爲安全起見,但願在工地發生事故時全部挖煤點的工人都能有一條出路逃到救援出口處。因而礦主決定在某些挖煤點設立救援出口,使得不管哪個挖煤點坍塌以後,其餘挖煤點的工人都有一條道路通向救援出口。
請寫一個程序,用來計算至少須要設置幾個救援出口,以及不一樣最少救援出口的設置方案總數。
輸入格式:
輸入文件有若干組數據,每組數據的第一行是一個正整數 N(N<=500),表示工地的隧道數,接下來的 N 行每行是用空格隔開的兩個整數 S 和 T,表示挖 S 與挖煤點 T 由隧道直接鏈接。輸入數據以 0 結尾。
輸出格式:
輸入文件中有多少組數據,輸出文件 output.txt 中就有多少行。每行對應一組輸入數據的 結果。其中第 i 行以 Case i: 開始(注意大小寫,Case 與 i 之間有空格,i 與:之間無空格,: 以後有空格),其後是用空格隔開的兩個正整數,第一個正整數表示對於第 i 組輸入數據至少需 要設置幾個救援出口,第二個正整數表示對於第 i 組輸入數據不一樣最少救援出口的設置方案總 數。輸入數據保證答案小於 2^64。輸出格式參照如下輸入輸出樣例。
輸入樣例#1:
9
1 3
4 1
3 5
1 2
2 6
1 5
6 3
1 6
3 2
6
1 2
1 3
2 4
2 5
3 6
3 7
0
輸出樣例#1:
Case 1: 2 4
Case 2: 4 1
Case 1 的四組解分別是(2,4),(3,4),(4,5),(4,6);
Case 2 的一組解爲(4,5,6,7)。
(這道題是道中文題不用解釋好開森~_(:з」∠)_)
咳咳。而後這道題同上也是要求割點的。= =||| 懶癌晚期不想說什麼了代碼裏分析
#include<bits/stdc++.h>
#define M 510
typedef long long ll;
using namespace std;
inline ll read() //讀優你懂的
{
ll x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
int n,m;
ll tim,pat,top,part,res,ans;
ll dfn[M],low[M];
ll num[M],stk[M];
bool vis[M];
struct Node{ int gd,es;}grp[M]; //強連通份量記錄割點數和非割點數你懂的
struct Edge{ int v; Edge *next;}*head[M]; //鄰接表存邊你懂的(只不過用了指針而已啦)
void add(int u,int v) { Edge *p=new(Edge); p->v=v; p->next=head[u]; head[u]=p; }
void tarjan(int u) //tarjan縮點你懂的
{
dfn[u]=low[u]=++tim;
for(Edge *i=head[u];i;i=i->next)
{
int v=i->v;
if(!dfn[v])
{
tarjan(v); low[u]=min(low[u] , low[v]);
if(dfn[u]<=low[v]) ++num[u]; //子樹的數目++(比起模板也就這裏變了一下吧)
}
else low[u]=min(low[u] , dfn[v]);
}
}
void dfs(int u) //dfs上再來求強連通份量
{
vis[u]=true; stk[++top]=u;
for(Edge *i=head[u];i;i=i->next)
{
int v=i->v;
if(vis[v]) continue;
dfs(v);
if(low[v]>=dfn[u])
{
++part;
int j=0;
do{
j=stk[top--];
if(num[j]) ++grp[part].gd;
else ++grp[part].es;
}while(j!=u);
++top;
}
}
}
int main()
{
int T=0;
while(true)
{
memset(num , 0 , sizeof(num));
memset(stk , 0 , sizeof(stk));
memset(vis , 0 , sizeof(vis));
memset(dfn , 0 , sizeof(dfn));
memset(low , 0 , sizeof(low));
memset(head, 0 ,sizeof(head));
for(int i=0;i<M;++i)grp[i].gd=grp[i].es=0;
pat=tim=part=top=ans=n=0; res=1;
/* 這些能夠放到子函數裏那樣看起來清楚點 */
m=read();
if(!m) return 0;
while(m--)
{
int u=read(),v=read();
n=max(n , max(u , v)); //題目中沒說幾個礦場咱們就找最大值存下來當礦場數
add(u,v); add(v,u);
}
for(int i=1;i<=n;++i) if(!dfn[i])
{
tarjan(i);
if(num[i]>0) //根節點的有效子樹數量要-1(固然這裏沒有這個if也沒事直接減減就行)
--num[i];
}
for(int i=1;i<=n;++i) //這時候再深搜找強連通份量(已排除根節點有效子樹數量的干擾)
if(!vis[i]) dfs(i);
for(int i=1;i<=part;++i)
{
if(grp[i].gd>=2) continue; //大於兩個割點的就不用建出口了,由於任意一個割點礦場毀了後,
//該強連通份量礦場裏的人還能夠經過剩下來的割點礦場逃到其餘強連通份量礦場裏找出口
if(grp[i].gd==1) { ++ans; res*=grp[i].es; }
//只有一個割點就要再建一個出口(方案數*該強連通份量礦場中非割點礦場的數量)
else if(grp[i].gd==0) { ans+=2; res*=(grp[i].es*(grp[i].es-1))/2; }
//沒有割點的話說明該強連通份量與外界徹底分離了,要建兩個出口以防萬一(可能建出口的那個礦場會炸)
}
printf("Case %d: %lld %lld\n",++T,ans,res);
}
}
= =||| 怎麼說好咧,這個題目本身都仍是有點疑問,等會兒再想一想。。。
那麼接下來我就稍微講講【wedding】這道題吧。題意就是給你個n和m,表示有n隊夫婦,編號爲0~n-1,其中0號夫婦今天辦了酒宴,而後這些夫婦中有m對人是不能坐在一列的。(好像說是通姦啥的?)那麼這m對人至關於兩兩排斥,不能同時坐在0號新郎那列(可是能夠同時坐在0號新娘那列),而且每對夫婦也不能夠坐在同一列(假設3號新郎坐在0號新郎那列,那麼3號新娘就只能坐在0號新娘那列,也就是和3號新郎不一樣的那列),而後的話就是要你求和0號新娘坐在同一列的夫婦的任意一種情況(任意一種情況求出來都能AC,也不知道是數據輸入的時候就保證了只有惟一解仍是評測的時候是一個一個狀況去對的,前者可能性較大)。好了那麼這道題講的也就差很少,其實本質上是一個2-SAT問題,不過是最終的答案變成了無矛盾組的取反而已,我也就很少說了這道題仍是有點作的價值滴~~~
OK,這篇專題就結束了,小夥伴們下次見~_(:з」∠)_
ヾ( ̄▽ ̄)Bye~Bye~ (喜歡請點贊不喜歡請評論)