Description
煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。
Input
输入文件有若干组数据,每组数据的第一行是一个正整数
N(N≤500)
,表示工地的隧道数,接下来的
N
行每行是用空格隔开的两个整数
Output
输入文件中有多少组数据,输出文件 output.txt 中就有多少行。
每行对应一组输入数据的 结果。其中第
i
行以
Sample Input
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
Sample Output
Case 1: 2 4
Case 2: 4 1
HINT
Case1 的四组解分别是 (2,4),(3,4),(4,5),(4,6) ;
Case2 的一组解为 (4,5,6,7) 。
Source
day1
solution
请移步PoPoQQQ巨佬的题解
注意开long long
和输出格式
太懒了不想写了
code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
template<typename T>
void input(T &x) {
x=0; T a=1;
register char c=getchar();
for(;c<'0'||c>'9';c=getchar())
if(c=='-') a=-1;
for(;c>='0'&&c<='9';c=getchar())
x=x*10+c-'0';
x*=a;
return;
}
#define MAXM 510
#define MAXN 510
struct Edge {
int u,v,next;
Edge(int u=0,int v=0,int next=0):
u(u),v(v),next(next) {}
};
Edge edge[MAXM<<1];
int head[MAXN],cnt;
void addedge(int u,int v) {
edge[++cnt]=Edge(u,v,head[u]);
head[u]=cnt;
return;
}
int dfn[MAXN],low[MAXN],timee;
bool cutpoint[MAXN];
int root,sum;
void tarjan(int now,int f) {
dfn[now]=low[now]=++timee;
for(int i=head[now];i;i=edge[i].next) {
int v=edge[i].v;
if(!dfn[v]) {
tarjan(v,now);
low[now]=min(low[now],low[v]);
if(low[v]>=dfn[now]) {
if(now!=root)
cutpoint[now]=true;
else sum++;
}
} else if(v!=f)
low[now]=min(low[now],dfn[v]);
}
return;
}
int col[MAXN],numcolor;
int cutsum,notcutsum;
void dfs(int now) {
col[now]=numcolor;
notcutsum++;
for(int i=head[now];i;i=edge[i].next) {
int v=edge[i].v;
if(cutpoint[v]&&col[v]!=numcolor) {
cutsum++;
col[v]=numcolor;
}
if(!col[v]) dfs(v);
}
return;
}
void _clear() {
memset(head,0,sizeof(head));
memset(col,0,sizeof(col));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(cutpoint,0,sizeof(cutpoint));
cnt=timee=numcolor=0;
}
int main() {
for(int Case=1;true;Case++) {
_clear();
int n=0,m;
input(m);
if(m==0) break;
for(int i=1;i<=m;i++) {
int u,v;
input(u),input(v);
addedge(u,v),
addedge(v,u);
n=max(n,u),n=max(n,v);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) {
sum=0,root=i;
tarjan(i,i);
if(sum>=2)
cutpoint[i]=true;
}
int ansA=0;
ll ansB=1;
for(int i=1;i<=n;i++)
if(!col[i]&&!cutpoint[i]) {
numcolor++;
cutsum=notcutsum=0;
dfs(i);
if(cutsum==0) {
ansA+=2;
ansB*=1ll*(notcutsum-1)*notcutsum/2;
}
if(cutsum==1) {
ansA++;
ansB*=1ll*notcutsum;
}
}
printf("Case %d: %d %lld\n",Case,ansA,ansB);
}
return 0;
}