2014 UESTC Training for Graph Theory J

来源:互联网 发布:嵌入式系统编程 扫描版 编辑:程序博客网 时间:2024/05/21 19:22
欧拉道路的问题
要求单词首位连接而且要求字典序最小
首先建图,为了满足字典序的要求,每个单词首尾字母连一条边
然后对图首节点排序,比如以a开头的所有单词排序
那么每个首字母单词就可以排序输出的时候就是字典序
另外的就是欧拉路的判断了,如果入度出度全部相等那么任意点开始DFS就可以,但是由于字典序要从第一个出现的字母开始DFS
其他情况下存在欧拉路的话就是一个点的入度比出度大一,另一个点出度比入度大1,那么就要从出度比入度大一的点开始DFS才可以
另外输出时要注意以栈来存储输出。因为当前虽然是字典序最小,但可能其可能不是真正的道路起点

里外里用给并查集判断联通

#include <map>#include <set>#include <list>#include <cmath>#include<cctype>#include <ctime>#include <deque>#include <stack>#include <queue>#include <cstdio>#include <string>#include <vector>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#define LL long long#define PI 3.1415926535897932626using namespace std;int gcd(int a, int b){return a % b == 0 ? b : gcd(b, a % b);}#define MAXN 30struct node{    int v,vis;    char name[25];    node()    {        v=-1;        vis=false;    }    bool operator < (const node &n) const    {         return strcmp(name,n.name)<0;    }};vector <node >G[MAXN];char path[1002][MAXN];int rear,N;bool used[MAXN];int fa[MAXN],inde[MAXN],outde[MAXN];int start;int find(int x){    return x==fa[x]?x:fa[x]=find(fa[x]);}void merge(int x,int y){    int a=find(x),b=find(y);    if (a==b) return ;    fa[a]=b;}void init(){    memset(used,false,sizeof(used));    memset(inde,0,sizeof(inde));    memset(outde,0,sizeof(outde));    rear=0;    start=-1;    for (int i=0;i<26;i++) { fa[i]=i;G[i].clear();}}void addedge(char *str){    int len=strlen(str);    int u=str[0]-'a',v=str[len-1]-'a';    node tmp;    tmp.v=v;    strcpy(tmp.name,str);    G[u].push_back(tmp);    used[u]=true;used[v]=true;    outde[u]++;inde[v]++;    merge(u,v);}bool judge_assem(){    int Count=0;    for (int i=0;i<26;i++)    {        if (used[i] && fa[i]==i) Count++;    }    //printf("%d\n",Count);    return Count==1;}bool judge_euler(){    int a=0,b=0;    for (int i=0;i<26;i++)        if (used[i])        {            if (inde[i]==outde[i]) continue;            if (inde[i]-outde[i]==1) a++;            else if (outde[i]-inde[i]==1){ b++;start=i;}//满足一个点出度比入度大一,一个点入度比出度大1            else return false;        }    if (a==0 && b==0) return true;//任意点出发,由字典序要从第一个used开始euler    else if (a==1 && b==1) return true;    return false;}void euler(int u){    for (int i=0;i<(int)G[u].size();i++)    {        int v=G[u][i].v;        if (!G[u][i].vis)        {            G[u][i].vis=true;            euler(v);            strcpy(path[rear++],G[u][i].name);        }    }}void print(){    for (int i=rear-1;i>=0;i--)    {        if (i==rear-1) printf("%s",path[i]);        else printf(".%s",path[i]);    }    putchar('\n');}void read(){   char tmp[30];   scanf("%d",&N);   for (int i=0;i<N;i++)   {       scanf("%s",tmp);       addedge(tmp);   }   for(int i=0;i<26;i++)   if(used[i])   {         sort(G[i].begin(),G[i].end());   }}int main(){   //freopen("sample.txt","r",stdin);    int T;    scanf("%d",&T);    while (T--)    {        init();        read();        bool flag=(judge_assem()&&judge_euler());        if (flag)        {            if (start==-1)            {                for (int i=0;i<26;i++)                if (used[i])               {                 euler(i);                 break;               }            }            else euler(start);            //printf("%d\n",rear);            print();        }        else printf("***\n");    }    return 0;}


0 0
原创粉丝点击