ACOJ的服务器简直是差到了一个令人发指的地步。于是SAC的出题人,也就是傻逼SOL,不得不强制要求每一个通过下载ACOJ软件包而搭建的分站,都为主站启动云端评测服务。
云评测服务是由网络来连接的。这样的网络连接是双向的;但是由于地理位置等因素的限制,并不是任意两台服务器都可以直接相连。ACOJ主站已经得到了可以直连的服务器的表,其中包含n个分站(包括主站)以及它们的m条连接情况,可以根据这个来分配各个分站的任务。
有一些分站的服主是SOL的脑残粉。他们会无条件地将他们的服务器提供给SOL。这些ACOJ分站称作“好站”。但是还有一些分站的服主是SOL黑。他们虽然拿到了ACOJ的服务端,但是并不愿意为SOL提供资源,于是利用黑科技关掉了云服务。也就是说,虽然主站仍然认为这些站点存在,但是它们不会起到任何作用——既不能传递通信,也不能进行评测。它们称作“坏站”。
经过千辛万苦的调查,SOL确定了ACOJ云评测系统中有最多k个坏站存在,而且这k个坏站似乎会使得ACOJ的云网络不再联通!大危机!
但是SOL太弱智了,并不能确定是哪k个。于是他请你来帮他找出任意一组可能会使得网络不再联通的k个站点,以便加强防范。
输入包含m+1行。
第1行3个整数n、m、k。
接下来m行,每行两个整数a、b,表示标号为a和b的站点可以直接相连。
输出包含1行。
不超过k个整数,表示能够将原图割开的任意一组节点组合。
因为使用了Special Judge,所以节点的顺序并不用担心。只需要满足能够割开原图即可。
如果不存在这样的站点集合,输出“How oversuspicious you are, SOL!”;如果网络不存在任何坏站时本来就无法连通,输出“Poor SOL!”。
4 4 2
1 2
2 3
3 4
4 1
1 3
4 6 2
1 2
2 3
3 4
4 1
1 3
2 4
How oversuspicious you are, SOL!
4 0 2
Poor SOL!
看完题发现是个np问题,然而发现k <= 3╮(╯▽╰)╭,于是就上大讨论术然后大力暴力于是就过了233.
代码如下
#include
#include
#include
#include
using namespace std;
const int sz = 60100;
int head[sz],nxt[sz],l[sz];
int dfn[501],low[501],dfs_clock;
bool is_cut[501];
int tot = 1,n,m,k;
bool use[501],vis[501];
void build_edge(int f,int t)
{
l[tot] = t;
nxt[tot] = head[f];
head[f] = tot ++;
}
int tarjan(int u,int fa)
{
int child = 0;
dfn[u] = low[u] = ++ dfs_clock;
for(int i = head[u] ; i ; i = nxt[i])
{
int v = l[i];
if(!dfn[v] && !use[v])
{
child ++;
low[v] = tarjan(v,u);
low[u] = min(low[u],low[v]);
if(low[v] >= dfn[u])
is_cut[u] = 1;
}
else if(v != fa && dfn[v] < low[u] && !use[v])
low[u] = dfn[v];
}
if(fa == 0 && child == 1)
is_cut[u] = 0;
return low[u];
}
int read()
{
int x = 0 , f = 1;
char in = getchar();
while(in < '0' || in > '9')
{
if(in == '-')
f = -1;
in = getchar();
}
while('0' <= in && in <= '9')
{
x = x * 10 + in - '0';
in = getchar();
}
return x * f;
}
void init()
{
dfs_clock = 0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(is_cut,0,sizeof(is_cut));
}
void dfs(int u)
{
vis[u] = 1;
for(int i = head[u] ; i ; i = nxt[i])
if(!use[l[i]] && !vis[l[i]])
dfs(l[i]);
return ;
}
int main()
{
n = read() , m = read() , k = read();
for(int i = 1 ; i <= m ; i ++)
{
int f = read() , t = read();
build_edge(f,t);
build_edge(t,f);
}
{
int ans = 0;
for(int i = 1 ; i <= n ; i ++)
if(!vis[i])
dfs(i),ans ++;
if(ans > 1)
{
puts("Poor SOL!");
return 0;
}
}
if(k == 1)
{
tarjan(1,0);
for(int i = 1 ; i <= n ; i ++)
if(is_cut[i])
{
printf("%d\n",i);
return 0;
}
}
if(k == 2)
{
for(int i = 1 ; i <= n ; i ++)
{
init();
use[i] = 1;
for(int j = 1 ; j <= n ; j ++)
if(!use[j])
{
tarjan(j,0);
break;
}
use[i] = 0;
for(int j = 1 ; j <= n ; j ++)
if(j != i && is_cut[j])
{
printf("%d %d\n",i,j);
return 0;
}
}
}
if(k == 3)
{
for(int i = 1 ; i <= n ; i ++)
{
for(int j = i + 1 ; j <= n ; j ++)
{
init();
use[i] = 1 , use[j] = 1;
for(int k = 1 ; k <= n ; k ++)
if(!use[k])
{
tarjan(k,0);
break;
}
use[i] = 0 , use[j] = 0;
for(int k = 1 ; k <= n ; k ++)
if(k != i && k != j && is_cut[k])
{
printf("%d %d %d\n",i,j,k);
return 0;
}
}
}
}
puts("How oversuspicious you are, SOL!");
return 0;
}
/*
6 7 1
1 2
1 3
1 4
2 5
3 5
4 5
5 6
*/