图论

内容


/* 
 * 次小生成树 
 * 求最小生成树时,用数组Max[i][j]来表示MST中i到j最大边权 
 * 求完后,直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案 
 * 点的编号从0开始 
 */ 
上海大学 ACM 模板  by kuangbin 
    94 / 173  ACM 模板  kuangbin 
 int pre[MAXN],id[MAXN],visit[MAXN],in[MAXN]; 
int zhuliu(int root,int n,int m,Edge edge[]) 
{ 
    int res = 0,u,v; 
    while(1) 
    { 
        for(int i = 0;i < n;i++) 
            in[i] = INF; 
        for(int i = 0;i < m;i++) 
            if(edge[i].u != edge[i].v && edge[i].cost < in[edge[i].v]) 
            { 
                pre[edge[i].v] = edge[i].u; 
                in[edge[i].v] = edge[i].cost; 
            } 
        for(int i = 0;i < n;i++) 
            if(i != root && in[i] == INF) 
                return -1;//不存在最小树形图 
        int tn = 0; 
        memset(id,-1,sizeof(id)); 
        memset(visit,-1,sizeof(visit)); 
        in[root] = 0; 
        for(int i = 0;i < n;i++) 
        { 
            res += in[i]; 
            v = i; 
            while( visit[v] != i && id[v] == -1 && v != root) 
            { 
                visit[v] = i; 
                v = pre[v]; 
            } 
            if( v != root && id[v] == -1 ) 
            { 
                for(int u = pre[v]; u != v ;u = pre[u]) 
                    id[u] = tn; 上海大学 ACM 模板  by kuangbin 
    94 / 173  ACM 模板  kuangbin 
 
                id[v] = tn++; 
            } 
        } 
        if(tn == 0)break;//没有有向环 
        for(int i = 0;i < n;i++) 
            if(id[i] == -1) 
                id[i] = tn++; 
        for(int i = 0;i < m;) 
        { 
            v = edge[i].v; 
            edge[i].u = id[edge[i].u]; 
            edge[i].v = id[edge[i].v]; 
            if(edge[i].u != edge[i].v) 
                edge[i++].cost -= in[v]; 
            else 
                swap(edge[i],edge[--m]); 
        } 
        n = tn; 
        root = id[root]; 
    } 
    return res; 
}
</pre><pre name="code" class="cpp">
void addedge(int u,int v,int w)
{
     edges[ecnt++]=Edge(u,v,w);
}
int zhu_liu()
{
    int weight=0,i,j,u,v,root=0;
    while (1)
    {
        for(i=0;i<N;i++){
            dist[i]=INF;
            num[i]=-1;
            s[i]=-1;
        }
        dist[root]=0;
        pre[root]=-1;
        int cnt=0;
        for (i=0;i<ecnt;i++){
            Edge e=edges[i];
            if (e.u==e.v) continue;
            if (dist[e.v]>e.w){
                dist[e.v]=e.w;
                pre[e.v]=e.u;
            }
        }
        for (i=0;i<N;i++){
            if (dist[i]==INF)
                return -1;
            weight+=dist[i];
            u=i;
            while (pre[u]!=-1&&s[u]!=i&&num[u]==-1)            {
                s[u]=i;
                u=pre[u];
            }
            if (s[u]==i){
                while (num[u]==-1){
                    num[u]=cnt;
                    u=pre[u];
                }
                cnt++;
            }
        }
        if (cnt==0) return weight;
        for (i=0;i<N;i++){
            if (num[i]==-1){
                num[i]=cnt++;
            }
        }
        for (i=0;i<ecnt;i++){
            Edge &e=edges[i];
            e.w-=dist[e.v];
            e.u=num[e.u];
            e.v=num[e.v];
        }
        root=num[root];
        N=cnt;
    }
    return weight;
}



#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
#define MAXM 10010
#define MAX 40
struct Edge
{
    int v,num;
    Edge(){}
    Edge(int x,int y)
    {
        this->v=x;
        this->num=y;
    }
};
string s[MAXM];
int n,in[MAX],out[MAX];
int mark[MAXM],E[MAXM],U[MAXM];
vector<Edge>G[MAX];
int parent[MAX],vis[MAX];
bool cmp(string a,string b)
{
    return a<b;
}
int find(int x)
{
    if (parent[x]>=0)
    {
        return parent[x]=find(parent[x]);
    }
    return x;
}
int check()
{
    int i,cnt=0,cntx=0,cnty=0,start=-1;;
    for (i=0;i<26;i++)
    {
        if (vis[i])
        {
            if (start==-1)
                start=i;
            if (parent[i]==-1)
            {
//                cout<<"cnt"<<endl;
                cnt++;
                if (cnt>1)
                    return -1;
            }
            if (in[i]-out[i]==-1)
            {
                start=i;
                cntx++;
            }
            else if (in[i]-out[i]==1)
            {
                cnty++;
            }
            else if (abs(in[i]-out[i])>1)
            {
//                cout<<"xxxx"<<endl;
                return -1;
            }
        }
        if (cntx>1||cnty>1)
        {
            return -1;
        }
    }
    return start;
}
int main()
{
    int T;
//    ios::sync_with_stdio(false);
//    freopen()
    cin>>T;
    while (T--)
    {
        cin>>n;
        int i,j,u,v,flag,L;
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        memset(mark,0,sizeof(mark));
        memset(parent,-1,sizeof(parent));
        memset(vis,0,sizeof(vis));
        for (i=0;i<26;i++)
        {
            G[i].clear();
        }
        for (i=0;i<n;i++)
        {
            cin>>s[i];
        }
        sort(s,s+n,cmp);
        for (i=0;i<n;i++)
        {
//            cout<<s[i]<<endl;
            u=s[i][0]-'a';
            L=s[i].size();
            v=s[i][L-1]-'a';
            U[i]=v;
            G[u].push_back(Edge(v,i));
            in[v]++,out[u]++;
            vis[u]=vis[v]=1;
            u=find(u);
            v=find(v);
            if (u!=v)
            {
                parent[u]=v;
            }
        }
        flag=check();
        if (flag<0)
        {
            cout<<"***"<<endl;
        }
        else
        {
            int cnt=0;
            stack<int>S;
            for (i=0;i<G[flag].size();i++)
            {
                Edge e=G[flag][i];
                if (!mark[e.num])
                {
                    mark[e.num]=1;
                    S.push(e.num);
                    break;
                }
            }
            while (!S.empty())
            {
                flag=0;
                int temp=S.top();
                u=U[temp];
                for (i=0;i<G[u].size();i++)
                {
                    Edge e=G[u][i];
                    if (!mark[e.num])
                    {
                        mark[e.num]=1;
                        S.push(e.num);
                        flag=1;
                        break;
                    }
                }
                if (!flag)
                {
//                    cout<<S.top()<<endl;
                    E[cnt++]=S.top();
                    S.pop();
                }
            }
            for (i=cnt-1;i>=0;i--)
            {
                cout<<s[E[i]];
                if (i!=0)
                {
                    cout<<".";
                }
            }
            cout<<endl;
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值