您的位置:首页 > 其它

Wannafly交流赛1: C. 腰带图(瞎搞)

2018-03-02 23:36 369 查看
链接:https://www.nowcoder.com/acm/contest/69/C

来源:牛客网

题目描述

一个n个点m条边的无向图,它若满足以下性质,我们就称它为腰带图:

1.n为>=6的偶数。
2.这个图恰有3/2*n条边。
3.存在所有点的一个排列p0,p1,...,pn-1,使得对于所有满足0<=i<n/2的整数i:

(1)点pi和点p(i+1) mod (n/2)间有边相邻。

(2)点pi+n/2和点pn/2+(i+1) mod (n/2)间有边相邻。

(3)点pi和点pi+n/2间有边相邻。

注:x mod y为x除以y的余数。

现在给你一个无向图,请判断他是否是腰带图。

输入描述:

输入的第一行有一个正整数T,代表询问数。
每个询问各占1+m行,当中的第1行有两个正整数n,m分别代表点数和边数,接下来m行当中的第i行包含两个整数xi,yi,代表点xi和点yi间有边相连。

输出描述:

每个询问的回答占1行,若此图不是腰带图,该行里只包含一个整数-1;若是腰带图,则输出n个数p0,p1,...,pn-1,其为任一个能证明此图是腰带图的0~n-1的排列。(意思就是题面里提到的该有的边都存在。)

把题目中的要求和样例画出来,你会发现腰带图中有两个主环,每个环上刚好n/2个点,并且这两个环n/2对点一一对应,8个点的腰带图具体如下:(0123在一个主环上,4567在另一个主环上)



n只有200,感觉可以瞎搞,下面给出一个O(3²n)的方法

①首先每个点的度数都必须为3,否则输出-1

②固定0号点(即p0一定为0),然后暴力与0号点相连的3个点,确定与0对应的点x

(x和0在不同的主环上,他们之间有一条边,即上图中的'4'号点)

③确定了图中的'0'和'4'后,就找下面两个点'1'和'5',找到之后接着找'2'和'6'……直到最后两个点'3'和'7'

这个很好办,它们必须没有被标记过并且有条边连接着他们,中间某个时候找不到就说明不行

④确定最后两个点是否和最一开始的两个固定的点相连,如果相连就OK,说明这是其中一组解

⑤如果固定与0号点相连的3个点都不能找到解,就输出-1

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct
{
int x;
int y;
}Res;
Res s[305];
int road[205][5], cnt[205], ans[205];
int Find(int x, int y)
{
int i;
for(i=1;i<=3;i++)
{
if(road[x][i]==y)
return 1;
}
return 0;
}
int main(void)
{
int T, i, j, k, n, m, x, y, x2, y2, p, q;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
memset(cnt, 0, sizeof(cnt));
for(i=1;i<=m;i++)
scanf("%d%d", &s[i].x, &s[i].y);
for(i=1;i<=m;i++)
{
x = s[i].x+1, y = s[i].y+1;
road[x][++cnt[x]] = y;
road[y][++cnt[y]] = x;
if(cnt[x]>=4 || cnt[y]>=4)
break;
}
if(i<=m)
{
printf("-1\n");
continue;
}
memset(ans, -1, sizeof(ans));
for(i=1;i<=3;i++)
{
x = 1, y = road[1][i];
ans[x] = 0, ans[y] = n/2;
for(j=1;j<=3;j++)
{
for(k=1;k<=3;k++)
{
x2 = road[x][j], y2 = road[y][k];
if(Find(x2, y2) && ans[x2]==-1 && ans[y2]==-1)
goto loop;
}
}
continue;
loop:;
for(j=2;j<=n/2-1;j++)
{
x = x2, y = y2;
ans[x] = j-1, ans[y] = j-1+n/2;
for(p=1;p<=3;p++)
{
for(q=1;q<=3;q++)
{
x2 = road[x][p], y2 = road[y][q];
if(Find(x2, y2) && ans[x2]==-1 && ans[y2]==-1)
goto loop2;
}
}
break;
loop2:;
}
if(j<=n/2-1)
{
memset(ans, -1, sizeof(ans));
continue;
}
x = x2, y = y2;
ans[x] = j-1, ans[y] = j-1+n/2;
for(p=1;p<=3;p++)
{
for(q=1;q<=3;q++)
{
x2 = road[x][p], y2 = road[y][q];
if(Find(x2, y2) && ans[x2]==0 && ans[y2]==n/2)
goto loop3;
}
}
memset(ans, -1, sizeof(ans));
continue;
loop3:;
printf("0");
for(j=1;j<=n-1;j++)
{
for(k=1;k<=n;k++)
{
if(ans[k]==j)
printf(" %d", k-1);
}
}
printf("\n");
break;
}
if(i==4)
printf("-1\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: