zoukankan      html  css  js  c++  java
  • hdu 1853 Cyclic Tour (二分匹配KM最小权值 或 最小费用最大流)

    Cyclic Tour

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others)
    Total Submission(s): 1197    Accepted Submission(s): 626


    Problem Description
    There are N cities in our country, and M one-way roads connecting them. Now Little Tom wants to make several cyclic tours, which satisfy that, each cycle contain at least two cities, and each city belongs to one cycle exactly. Tom wants the total length of all the tours minimum, but he is too lazy to calculate. Can you help him?
     
    Input
    There are several test cases in the input. You should process to the end of file (EOF).
    The first line of each test case contains two integers N (N ≤ 100) and M, indicating the number of cities and the number of roads. The M lines followed, each of them contains three numbers A, B, and C, indicating that there is a road from city A to city B, whose length is C. (1 ≤ A,B ≤ N, A ≠ B, 1 ≤ C ≤ 1000).
     
    Output
    Output one number for each test case, indicating the minimum length of all the tours. If there are no such tours, output -1. 
     
    Sample Input
    6 9 1 2 5 2 3 5 3 1 10 3 4 12 4 1 8 4 6 11 5 4 7 5 6 9 6 5 4 6 5 1 2 1 2 3 1 3 4 1 4 5 1 5 6 1
     
    Sample Output
    42 -1
    Hint
    In the first sample, there are two cycles, (1->2->3->1) and (6->5->4->6) whose length is 20 + 22 = 42.
     
    Author
    RoBa@TJU
     
    Source
     
    Recommend
    lcy   |   We have carefully selected several similar problems for you:  1533 3395 3315 2448 3061 
     

    题意:

    给一个图,要求用若干个环遍历全部点,求最短路程。

    二分匹配KM最小权值做法:

     1 //46MS    284K    2108 B    C++ 
     2 /*
     3     二分匹配:
     4         KM算法最小权值模板题... 
     5 */ 
     6 #include<stdio.h>
     7 #include<string.h>
     8 #define inf 0x7ffffff
     9 int g[105][105];
    10 int slack[105];
    11 int match[105];
    12 int lx[105],ly[105],visx[105],visy[105];
    13 int n,m;
    14 int Min(int a,int b)
    15 {
    16     return a<b?a:b;
    17 }
    18 int Max(int a,int b)
    19 {
    20     return a>b?a:b;
    21 }
    22 int dfs(int x)
    23 {
    24     visx[x]=1;
    25     for(int i=1;i<=n;i++){
    26         if(!visy[i]){
    27             if(lx[x]+ly[i]==g[x][i]){
    28                 visy[i]=1;
    29                 if(match[i]==-1 || dfs(match[i])){
    30                     match[i]=x;
    31                     return 1;
    32                 }
    33             }else{
    34                 slack[i]=Min(slack[i],lx[x]+ly[i]-g[x][i]);
    35             }
    36         }
    37     }
    38     return 0;
    39 }
    40 void KM()
    41 {
    42     memset(match,-1,sizeof(match));
    43     for(int i=0;i<=n;i++) lx[i]=-inf;
    44     memset(ly,0,sizeof(ly));
    45     for(int i=1;i<=n;i++)
    46         for(int j=1;j<=n;j++)
    47             lx[i]=Max(lx[i],g[i][j]);
    48     for(int i=1;i<=n;i++){
    49         for(int j=1;j<=n;j++) 
    50             slack[j]=inf;
    51         while(true){
    52             memset(visx,0,sizeof(visx));
    53             memset(visy,0,sizeof(visy));
    54             if(dfs(i)) break;
    55             int temp=inf;
    56             for(int j=1;j<=n;j++)
    57                 if(!visy[j]) 
    58                     temp=Min(temp,slack[j]);
    59             for(int j=1;j<=n;j++){
    60                 if(visx[j]) lx[j]-=temp;
    61                 if(visy[j]) ly[j]+=temp;
    62                 else slack[j]-=temp;
    63             }
    64         }
    65     
    66     }
    67 }
    68 int main(void)
    69 {
    70     int a,b,c;
    71     while(scanf("%d%d",&n,&m)!=EOF)
    72     {
    73         for(int i=0;i<=n;i++)
    74             for(int j=0;j<=n;j++)
    75                 g[i][j]=-inf;
    76         for(int i=0;i<m;i++){
    77             scanf("%d%d%d",&a,&b,&c);
    78             if(-c>g[a][b]) 
    79                 g[a][b]=-c;
    80         }
    81         KM();
    82         int ans=0;
    83         for(int i=1;i<=n;i++){
    84             if(match[i]==-1 || g[match[i]][i]==-inf){
    85                 ans=inf;
    86                 break;
    87             }
    88             ans+=g[match[i]][i];
    89         }
    90         if(ans==inf) puts("-1");
    91         else printf("%d
    ",-ans);
    92     }
    93     return 0;
    94 }
    95  
    View Code

    最小费用最大流做法:

      1 //218MS    656K    2377 B    C++
      2 /*
      3 
      4     第一题最小费用最大流...基本都是抄= =
      5     注意边的初始化、添加和修改.. 
      6 
      7 */
      8 #include<iostream>
      9 #include<queue>
     10 #define inf 0x7ffffff
     11 #define N 105
     12 using namespace std;
     13 struct node{
     14     int u,v,c,w;
     15     int next;   
     16 }edge[4*N*N];
     17 int n,m,edgenum,sumflow;
     18 int head[4*N],d[4*N],pp[4*N]; //pp记录增广链 
     19 bool vis[4*N];
     20 void init() //初始化 
     21 {
     22     edgenum=0;
     23     memset(head,-1,sizeof(head));
     24 }
     25 void addedge(int u,int v,int c,int w) //添加双向边 
     26 {
     27     edge[edgenum].u=u;
     28     edge[edgenum].v=v;
     29     edge[edgenum].c=c;
     30     edge[edgenum].w=w;
     31     edge[edgenum].next=head[u];
     32     head[u]=edgenum++;
     33     edge[edgenum].u=v;
     34     edge[edgenum].v=u;
     35     edge[edgenum].c=0;  //逆向边没流量 
     36     edge[edgenum].w=-w; //值取负 
     37     edge[edgenum].next=head[v];
     38     head[v]=edgenum++;
     39 }
     40 bool spfa() //求最短路 
     41 {
     42     queue<int>Q;
     43     memset(vis,false,sizeof(vis));
     44     memset(pp,-1,sizeof(pp));
     45     for(int i=0;i<=2*(n+1);i++) d[i]=inf;
     46     vis[0]=true;
     47     d[0]=0;
     48     Q.push(0);
     49     while(!Q.empty()){
     50         int u=Q.front();
     51         Q.pop();
     52         vis[u]=false;
     53         for(int i=head[u];i!=-1;i=edge[i].next){
     54             int v=edge[i].v;
     55             if(edge[i].c && d[v]>d[u]+edge[i].w){
     56                 d[v]=d[u]+edge[i].w;
     57                 pp[v]=i;
     58                 if(!vis[v]){
     59                     Q.push(v);
     60                     vis[v]=true;
     61                 }
     62             }
     63         }
     64     }
     65     if(d[2*n+1]==inf) return false;
     66     return true;
     67 }
     68 int MCMF()
     69 {
     70     int t=2*n+1;
     71     int flow=0;
     72     int mincost=0;
     73     sumflow=0;
     74     while(spfa()){
     75         int minflow=inf+1;
     76         for(int i=pp[t];i!=-1;i=pp[edge[i].u])
     77             if(edge[i].c<minflow)
     78                 minflow=edge[i].c;
     79         flow+=minflow;
     80         for(int i=pp[t];i!=-1;i=pp[edge[i].u]){ //调整增广链 
     81             edge[i].c-=minflow;
     82             edge[i^1].c+=minflow; //逆向边 
     83         }
     84         mincost+=d[t]*minflow;
     85     }
     86     sumflow=flow;
     87     return mincost;
     88 }
     89 int main(void)
     90 {
     91     int a,b,c;
     92     while(scanf("%d%d",&n,&m)!=EOF)
     93     {
     94         init();
     95         for(int i=1;i<=n;i++){
     96             addedge(0,i,1,0);
     97             addedge(n+i,2*n+1,1,0);
     98         }
     99         for(int i=0;i<m;i++){
    100             scanf("%d%d%d",&a,&b,&c);
    101             addedge(a,b+n,1,c);
    102         }
    103         int ans=MCMF();
    104         if(sumflow!=n) puts("-1");
    105         else printf("%d
    ",ans);    
    106     }
    107     return 0;
    108 }
    View Code
  • 相关阅读:
    python基本数据类型之整型和浮点型
    Java学习路线
    Linux学习笔记之VIM
    Java基础之流程控制
    Linux学习笔记之Shell
    Java基础之数据类型
    论文提交说明
    IDEA安装教程
    Link summary for writing papers
    1 类基础知识
  • 原文地址:https://www.cnblogs.com/GO-NO-1/p/3423074.html
Copyright © 2011-2022 走看看