• noip模拟


    2、世界人民大团结
    greatunion.cpp/in/out
    1s / 256M
    【题目描述】
    现在,世界的主题是和平与发展。社会学博士老 Z 认为,要实现和平发展,首先要实现
    世界人民大团结。
    世界上有 n 个人。他们胸前和背后各有一个自然数,大于或等于 0 且小于或等于 6。两
    个身上带有某个相同数字的人把身上相同的数字合在一起,就实现了团结。比如,(0,1)(1,2)
    就实现了团结,而(0,1)(2,1)和(0,0)(1,2)都不是团结。把数合在一起的方法,是胸靠胸、背靠
    背、背靠胸或胸靠背。
    请判断世界人民能否实现大团结。如果能,请输出大团结的实现方案。
    【输入】
    第一行,一个正整数 n,表示世界上有 n 个人。
    剩余 n 行,每行是用空格隔开的两个自然数,大于等于 0 且小于等于 6,第(1+i)行表示第 i
    个人胸前和背后的数字。
    【输出】
    如大团结可以实现,输出 n 行,每行两个空格隔开的数字。第一个是人的编号(同输入);
    第二个是“-”或“+”,
    “+”表示这个人胸在前,背在后,“-”反之。人们按照你输出的顺
    序和面对的方向从前到后站立。具体参见样例。
    如大团结不能实现,输出一行“No Solution”(不含引号)

    【样例输入】
    5
    1 2
    2 4
    2 4
    6 4
    2 1
    【样例输出】
    2 -
    5 +
    1 +
    3 +
    4 -
    【数据规模】
    对于 100%的数据,1<=n<=100

    题解:由于每个人都要用到,就相当于一个以[0,6]为顶点,以人为边的无项图,大团结就是无项图的欧拉回路。

    欧拉回路存在的充要条件(在连通图中) 每个点的度为偶数(无向图) 每个点的入度出度相等(有向图) 欧拉路存在的必要条件: 有且仅有两个点的度为奇数(无向图) 总的入度和等于总的出度和,有且仅有两个点的入度、出度差为1,其他点相等(有向图)。

    与二分图匹配算法类似,是一个深度优先遍历的过程,时间复杂度O(M)(因为一条边最多被访问一次)。核心代码(边是用边表存储的而不是邻接链表,因为无向图中需要对其逆向的边进行处理,在有向图中,可以用邻接链表存储边):

    code;

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    int n,map[10][10],S,T,top,ans[100010],tot,u,x[110],y[110],v,d[110];
    void dfs(int u)
    {
      for(int i=1;i<=7;i++)
        if(map[u][i])
          {
        map[u][i]--,map[i][u]--;
        d[u]--,d[i]--;
        dfs(i);
          }
      ans[++top]=u;
    }
    bool cal(int u,int v,int t)
    {
      if((u==x[t]&&v==y[t])||(u==y[t]&&v==x[t]))return 1;
      return 0;
    }
    int main()
    {
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
        {
          scanf("%d%d",&x[i],&y[i]);x[i]++,y[i]++;
          d[x[i]]++,d[y[i]]++;
          map[x[i]][y[i]]++,map[y[i]][x[i]]++;
        }
      for(int i=1;i<=7;i++)if(d[i]&1)tot++;
      if(tot!=0&&tot!=2){puts("No Solution");return 0;}
      for(int i=1;i<=7;i++)
        {
          if(d[i]&1)
        {
          if(S==0)S=i;
          else T=i;
        }
          if(d[i]&&!tot)S=i;
        }
      dfs(S);
      for(int i=1;i<=7;i++)
        if(d[i]){puts("No Solution");return 0;}
      for(int i=1;i<top;i++)
        for(int j=1;j<=n;j++)
          if(cal(ans[i],ans[i+1],j))//相邻入栈一定有边相连
          {
        printf("%d",j);
        if(x[j]==ans[i])puts(" +");
        else puts(" -");
        x[j]=y[j]=-1;
        break;
          }
      return 0;
    }
  • 相关阅读:
    解决UITableView中Cell重用机制导致内容出错的方法总结
    Hdu 1052 Tian Ji -- The Horse Racing
    Hdu 1009 FatMouse' Trade
    hdu 2037 今年暑假不AC
    hdu 1559 最大子矩阵
    hdu 1004 Let the Balloon Rise
    Hdu 1214 圆桌会议
    Hdu 1081 To The Max
    Hdu 2845 Beans
    Hdu 2955 Robberies 0/1背包
  • 原文地址:https://www.cnblogs.com/lxykk/p/7754701.html
Copyright © 2020-2023  润新知