sgu-252 Railway Communication

59 篇文章 1 订阅
4 篇文章 0 订阅
题目大意:

给定一个无向图,顶点数为 N(N<=100) ,边数为 M(M<=1000) ,每条边有一个非负的权值,要你求出一个边权和最小的最小路径覆盖。

解题思路:

不说什么了,最小费用最大流,直接裸上就行了,有一个问题就是输出,坑了我一个小时啊,输出要求对于每条路径从起点输出到终点,而不能乱序输出路径上的点。

AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>

using namespace std;

int N,M;
struct bian_
{
    int aim;
    int next;
}bian[4010]={{0,0}};
int G[210][210]={{0}};
int F[210][210]={{0}};
int cost[210][210]={{0}};
int dui[4010]={0};
int duip=0;
int dist[210]={0};
int fa[210]={0};
int st=0,en=0;
int hash[210]={0};
int First[210]={0};
int bp=0;
int son[210]={0};

bool SPFA()
{
    memset(dist,0x3f3f3f3f,sizeof(dist));
    duip=0;
    dist[0]=0;
    dui[++duip]=0;
    fa[0]=0;
    hash[0]=1;
    for(int i=1;i<=duip;i++)
    {
        int u=dui[i];
        for(int p=First[u];p!=0;p=bian[p].next)
        {
            int v=bian[p].aim;
            if(G[u][v]-F[u][v]==0) continue;
            if(dist[v]>dist[u]+cost[u][v])
            {
                fa[v]=u;
                dist[v]=dist[u]+cost[u][v];
                if(hash[v]==0)
                {
                    hash[v]=1;
                    dui[++duip]=v;
                }
            }
        }
        hash[u]=0;
    }
    if(dist[en]==0x3f3f3f3f) return false;
    return true;
}

void dfs(int k)
{
    if(k==0) return;
    dfs(fa[k]);
    F[fa[k]][k]++;
    F[k][fa[k]]--;
    return;
}

void Add(int p,int q)
{
    bp++;
    bian[bp].next=First[p];
    bian[bp].aim=q;
    First[p]=bp;
    return;
}

int main()
{
    scanf("%d%d",&N,&M);
    en=N*2+1;
    for(int i=1;i<=M;i++)
    {
        int p,q,r;
        scanf("%d%d%d",&p,&q,&r);
        cost[p][q+N]=r;
        cost[q+N][p]=-r;
        G[p][q+N]=1;
        Add(p,q+N);
        Add(q+N,p);
    }
    for(int i=1;i<=N;i++)
    {
        Add(0,i);
        Add(i,0);
        Add(i+N,en);
        Add(en,i+N);
        G[0][i]=G[i+N][en]=1;
    }
    int ans=0;
    int num=0;
    for(;SPFA();)
    {
        ans+=dist[en];
        dfs(en);
        num++;
    }
    cout<<N-num<<' '<<ans<<endl;
    memset(fa,-1,sizeof(fa));
    memset(son,-1,sizeof(son));
    for(int i=1;i<=N;i++)
        for(int j=1;j<=N;j++)
            if(F[i][j+N]==1)
            {
                son[i]=j;
                fa[j]=i;
            }
    for(int i=1;i<=N;i++)
    {
        if(hash[i]==1 || fa[i]!=-1) continue;
        int prt[110]={0};
        int ss=0;
        for(int j=i;j!=-1;)
        {
            hash[j]=1;
            prt[++ss]=j;
            j=son[j];
        }
        printf("%d ",ss);
        for(int j=1;j<=ss;j++) printf("%d ",prt[j]);
        puts("");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值