zoukankan      html  css  js  c++  java
  • uestc 方老师的分身IV

    类似POJ1386,参考的大神的博客

    首先明确思路:

    是否为连通图(并查集解决) -> 是否存在欧拉路径  ->  是否存在欧拉回路   (是,则选取字典序最小的输出,否则直接输出可行解)

    注意区分有向图和无线图存在欧拉路径或者欧拉回路的条件:

    无向图: G为连通图,并且G仅有两个奇度节点或者无奇度节点

      推论:1.当G是仅有两个奇度节点的连通图时,G的欧拉通路必以此两个结点为端点

         2.当G时无奇度结点的连通图时,G必有欧拉回路

         3.G为欧拉图(存在欧拉回路)的充分必要条件是G为无奇度节点的连通图

    有向图:D为有向图,D的基图连通,并且所有顶点的出度与入度相等;或者除两个定点外,其余顶点的出度和入度都相等,而这两个顶点中一个顶点的出度与入度之差为1,另一个顶点的出度与入度之差为1

      推论:1.当D除出、入度之差为1,-1的两个顶点之外,其余顶点的出度与入度都相等时,D的有向欧拉通路必以出入度之差为1的顶点作为始点,以出入度之差为-1的顶点作为终点

         2.当D的所有顶点的出入度都相等时,D中存在有向欧拉回路

         3.有向图D为有向欧拉回路的充分必要条件是D的基图为连通图,并且所有顶点的出入度都相等

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<string>
      6 #include<queue>
      7 #include<algorithm>
      8 #include<map>
      9 #include<iomanip>
     10 #include<climits>
     11 #include<string.h>
     12 #include<cmath>
     13 #include<stdlib.h>
     14 #include<vector>
     15 #include<stack>
     16 #define INF 1000000007
     17 #define MAXN 40010
     18 #define Mod 1000007
     19 #define N 2010
     20 #define NN 30
     21 #define sigma_size 3
     22 const int maxn = 6e5 + 10;
     23 using namespace std;
     24 typedef long long LL;
     25 
     26 struct node{
     27     int u, v, next;
     28     string w;
     29 }G[N];
     30 
     31 int head[NN], fa[NN], ind[NN], outd[NN], vis[NN];
     32 int t, cnt, start, k;
     33 int evis[N];
     34 string ss[N];
     35 string ans[N];
     36 int T, n;
     37 
     38 bool cmp(string a, string b)
     39 {
     40     return a > b;
     41 }
     42 
     43 int findset(int x)
     44 {
     45     if (fa[x] == x) return x;
     46     return fa[x] = findset(fa[x]);
     47 }
     48 
     49 void merg(int a, int b)
     50 {
     51     int x = findset(a);
     52     int y = findset(b);
     53     if (y != x) {
     54         fa[x] = y;
     55     }
     56 }
     57 
     58 void addedge(int u, int v, string w)
     59 {
     60     G[t].u = u;
     61     G[t].v = v;
     62     G[t].w = w;
     63     G[t].next = head[u];
     64     head[u] = t++;
     65     outd[u]++;
     66     ind[v]++;
     67     vis[u] = vis[v] = 1;
     68     merg(u, v);
     69 }
     70 
     71 void read()
     72 {
     73     cin >> n;
     74     for (int i = 1; i <= n; ++i)
     75         cin >> ss[i];
     76     sort(ss + 1, ss + n + 1, cmp);
     77     for (int i = 1; i <= n; ++i) {
     78         int u = ss[i][0] - 'a';
     79         int v = ss[i][ss[i].length() - 1] - 'a';
     80         addedge(u, v, ss[i]);
     81     }
     82 }
     83 
     84 void init()
     85 {
     86     t = 1;
     87     for (int i = 0; i < 30; ++i)
     88         fa[i] = i;
     89     memset(ind, 0, sizeof(ind));
     90     memset(outd, 0, sizeof(outd));
     91     for (int i = 0; i <= 2000; i++)
     92     {
     93         G[i].u = G[i].v = G[i].next = 0;
     94         G[i].w = "";
     95     }
     96     memset(head, -1, sizeof(head));
     97     memset(evis, 0, sizeof(evis));
     98     memset(vis, 0, sizeof(vis));
     99     for (int i = 0; i < 2010; ++i)
    100         ans[i] = "";
    101 }
    102 
    103 bool Euler_Path()
    104 {
    105     int one = 0;
    106     int none = 0;
    107     int tot = 0;
    108     start = -1;
    109     for (int i = 0; i < 26; ++i) {
    110         if (vis[i] == 0) continue;
    111         //int tmp = findset(i);
    112         if (findset(i) == i) tot++;
    113         //cout << tot << endl;
    114         if (ind[i] == outd[i] + 1) none++;
    115         else if (ind[i] + 1 == outd[i]) {
    116             one++;
    117             start = i;
    118         }
    119         else if (ind[i] != outd[i])
    120             return false;
    121     }
    122     if (tot != 1) return false;
    123     if ((one == none && one == 1) || (one == none && one == 0)) {
    124         if (start == -1) {
    125             for (int i = 0; i < 26; ++i) {
    126                 if (vis[i] && outd[i] > 0) {
    127                     start = i;
    128                     return true;
    129                 }
    130             }
    131         }
    132         if (one == none && one == 1) return true;
    133         return false;
    134     }
    135     return false;
    136 }
    137 
    138 
    139 void dfs(int v, int flag)
    140 {
    141     for (int i = head[v]; i != -1; i = G[i].next) {
    142         if (!evis[i]){
    143             evis[i] = 1;
    144             dfs(G[i].v, i);
    145         }
    146     }
    147     if (flag != -1)
    148         ans[cnt++] = G[flag].w;
    149 }
    150 void process()
    151 {
    152     init();
    153     read();
    154     if (Euler_Path()) {
    155         cnt = 0;
    156         dfs(start, -1);
    157         for (int i = cnt - 1; i >= 0; --i) {
    158             cout << ans[i];
    159             if (i != 0) cout << ".";
    160             else cout << endl;
    161         }
    162     }
    163     else puts("***");
    164 }
    165 
    166 int main()
    167 {
    168     cin >> T;
    169     while (T--) {
    170         process();
    171     }
    172     //system("pause");
    173     return 0;
    174 }
  • 相关阅读:
    问题:android学习内容破碎,我个人关于如何学习android的一些个人经历
    问题:一球从某高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第n次落地时,共经过多少米?第n次反弹多高?
    问题:alias设置与删除
    问题:从键盘读取特定类型的数据(使用Scanner读取int类型)
    求一个数组当中最大(最小)值的两种计算方法
    Mysql5.7安装
    maven下载及安装
    Ubuntu下修改DNS重启也能用的方法
    删除CNNIC证书
    字符编码ASCII, Unicode和UTF-8概念扫盲
  • 原文地址:https://www.cnblogs.com/usedrosee/p/4300314.html
Copyright © 2011-2022 走看看