p1693 [zjoi2004]嗅探器——dfnlow經典題目
阿新 • • 發佈:2018-12-10
題目
描述 Description
某軍搞資訊對抗實戰演習.紅軍成功地侵入了藍軍的內部網路.藍軍共有兩個資訊中心.紅軍計劃在某臺中間伺服器上安裝一個嗅探器,從而能夠偵聽到兩個資訊中心互相交換的所有資訊.但是藍軍的網路相當的龐大,資料包從一個資訊中心傳到另一個資訊中心可以不止有一條通路.現在需要你儘快地解決這個問題.應該把嗅探器安裝在哪個中間伺服器上才能保證所有的資料包都能被捕獲?
輸入格式 Input Format
第一行一個整數n(1<=n<=100000),表示藍軍網路中伺服器的數目.
接下來若干行是對藍軍網路的拓撲結構描述.每行是兩個整數i,j表示編號為I和編號為j的兩臺伺服器間存在連線(顯然連線是雙向的).伺服器的編號從1開始.描述一兩個0結束.再接下來一行是兩個整數a,b分別表示兩個中心伺服器的編號.
輸出格式 Output Format
如果有多個解輸出編號最小的一個.如果找不到任何解,輸出”No solution”.
樣例輸入 Sample Input
5
2 1
2 5
1 4
5 3
2 3
5 1
0 0
4 2
樣例輸出 Sample Output
1
時間限制 Time Limitation
1s
註釋 Hint
部分小資料
來源 Source
zjoi2004
資料加強來自 2017屆 楊曉虎 嶽川夢真
程式碼
#include<bits/stdc++.h>
using namespace std;
const int _=200010;
inline int read()
{
int f=1,num=0;
char ch=getchar();
while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); }
while (ch>='0'&&ch<='9') num=(num<<1)+(num<<3)+ch-'0', ch=getchar();
return num*f;
}
int ver[_],Next[_],head[_],len;
void add(int x,int y)
{
ver[++len]=y,Next[len] =head[x],head[x]=len;
}
int s,t,ans=999999999;
int dfn[_],low[_],id=0;
bool v[_];
void tarjan(int x,int root)
{
dfn[x]=low[x]=++id;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i];
if(!dfn[y])
{
tarjan(y,x);
low[x]=min(low[x],low[y]);
if (x!=s&&low[y]>=dfn[x]&&dfn[t]>=dfn[y]&&low[t]>=dfn[x])
ans=min(ans,x);
}
else if (y!=root)
low[x]=min(low[x],dfn[y]);
}
}
int main()
{
memset(v,0,sizeof(v));
int n=read();
while (1)
{
int x=read(),y=read();
if (!x&&!y) break;
add(x,y),add(y,x);
}
s=read(),t=read();
tarjan(s,0);
if (ans>n) printf("No solution\n");
else printf("%d\n",ans);
return 0;
}