zoukankan      html  css  js  c++  java
  • HIT 2739

    题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=2739

    Time limit : 1 sec Memory limit : 64 M

    A Chinese postman is assigned to a small town in China to deliver letters. In this town, each street is oriented and connects exactly two junctions. The postman's task is to start at the post office and pass each street at least once to deliver letters. At last, he must return to the post office.

    Can you help him to make sure whether there exist feasible routes for him and find the minimum distance from all the feasible routes.

    Input

    Input contains multiple test cases. The first line is an integer T, the number of test cases. Each case begins with two integers N, M, with 2 ≤ N ≤ 100, 1 ≤ M ≤ 2000, representing the number of junctions and the number of streets respectively.

    Then M lines will follow, each denoting a street. A street is represented by three integers u, v, d, with 0 ≤ u, v < N, 0 < d ≤ 1000, meaning this street whose length is d connects the junction u and v and the postman can only travel from junction u to v. Junctions are numbered from 0 to N-1. Junction 0 is always the post office. Note that there may be more than one street connecting the same pair of junctions.

    Output

    Output one line for each test case. If there exist feasible routes for the postman, output the minimum distance. Otherwise, output -1.

    Sample Input

    3
    2 1
    0 1 3
    4 4
    0 1 1
    1 2 2
    2 3 3
    3 0 4
    4 7
    0 1 1
    1 2 2
    2 3 3
    3 0 4
    1 3 5
    3 1 2
    1 3 2

    Sample Output

    -1
    10
    21

    题意:

     带权有向图上的中国邮路问题:

     一名邮递员需要经过每条有向边至少一次,最后回到出发点;

     一条边多次经过权值要累加,问最小总权值是多少。(2 <= N <= 100, 1 <= M <= 2000)

    构图:

     首先是比较理论的部分:

      

      

     因而有:

      (优先判断:若原图的基图不连通,或者存在某个点的入度或出度为 0 则无解,then可以直接跳到下一个test case;)

      统计所有点的 D[i] = outdegree[i] - indegree[i];

      对于 D[i] < 0 的点,加边(s, i, Di, 0);对于 D[i] > 0 的点,加边(i, t, -Di, 0);

      (判断:若所有D[i]全为0,直接输出sum = Σ( all D[i][j] )  ,其中 D[i][j] 为边(i, j)的权值,then可以直接跳到下一个test case;)

      对原图中的每条边(i, j),在网络中加边(i, j, ∞, D[i][j]);

      求一次最小费用最大流,费用加上原图所有边权和即为结果。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<queue>
      5 #define MAXN 105
      6 #define MAXM 2*(2005+2*MAXN)
      7 #define INF 0x3f3f3f3f
      8 using namespace std;
      9 int n,m;
     10 struct Edge{
     11     int u,v,c,f,a;
     12 };
     13 struct MCMF
     14 {
     15     int s,t,ne;
     16     Edge E[MAXM];
     17     int head[MAXN],next[MAXM];
     18     int vis[MAXN];
     19     int d[MAXN];
     20     int pre[MAXN];
     21     int aug[MAXN];
     22     void init()
     23     {
     24         ne=0;
     25         memset(head,-1,sizeof(head));
     26     }
     27     void addedge(int from,int to,int cap,int cost)
     28     {
     29         E[ne].u=from, E[ne].v=to, E[ne].c=cap, E[ne].f=0, E[ne].a=cost;
     30         next[ne]=head[from]; head[from]=ne++;
     31         E[ne].u=to, E[ne].v=from, E[ne].c=0, E[ne].f=0, E[ne].a=-cost;
     32         next[ne]=head[to]; head[to]=ne++;
     33     }
     34     bool SPFA(int s,int t,int &flow,int &cost)
     35     {
     36         memset(d,INF,sizeof(d));
     37         memset(vis,0,sizeof(vis));
     38         d[s]=0, vis[s]=1, pre[s]=0, aug[s]=INF;
     39         queue<int> q;
     40         q.push(s);
     41         while(!q.empty())
     42         {
     43             int now=q.front(); q.pop();
     44             vis[now]=0;
     45             for(int i=head[now];i!=-1;i=next[i])
     46             {
     47                 Edge& e=E[i];
     48                 int nex=e.v;
     49                 if(e.c>e.f && d[nex]>d[now]+e.a)
     50                 {
     51                     d[nex]=d[now]+e.a;
     52                     pre[nex]=i;
     53                     aug[nex]=min(aug[now],e.c-e.f);
     54                     if(!vis[nex])
     55                     {
     56                         q.push(nex);
     57                         vis[nex]=1;
     58                     }
     59                 }
     60             }
     61         }
     62         if(d[t]==INF) return 0;
     63         flow+=aug[t];
     64         cost+=d[t]*aug[t];
     65         for(int i=t;i!=s;i=E[pre[i]].u)
     66         {
     67             E[pre[i]].f+=aug[t];
     68             E[pre[i]^1].f-=aug[t];
     69         }
     70         return 1;
     71     }
     72     int mincost()
     73     {
     74         int flow=0,cost=0,cnt=0;
     75         while(SPFA(s,t,flow,cost));
     76         return cost;
     77     }
     78 }mcmf;
     79 
     80 int outd[MAXN],ind[MAXN],sum;
     81 int main()
     82 {
     83     int t;
     84     scanf("%d",&t);
     85     while(t--)
     86     {
     87         scanf("%d%d
    ",&n,&m);
     88         
     89         memset(outd,0,sizeof(outd));
     90         memset(ind,0,sizeof(ind));
     91         mcmf.s=0, mcmf.t=n+1; mcmf.init();
     92         sum=0;
     93         
     94         for(int i=1,u,v,d;i<=m;i++)
     95         {
     96             scanf("%d%d%d",&u,&v,&d);
     97             u++, v++, sum+=d;
     98             mcmf.addedge(u,v,INF,d);
     99             outd[u]++;
    100             ind[v]++;
    101         }
    102         
    103         bool hasAns=1,all_d_is_zero=1;
    104         for(int i=1,d;i<=n;i++)
    105         {
    106             if(outd[i]==0 || ind[i]==0)//显然不能有欧拉回路 
    107             {
    108                 hasAns=0;
    109                 break;
    110             }
    111             d=outd[i]-ind[i];
    112             if(d!=0) all_d_is_zero=0;
    113             if(d>0) mcmf.addedge(i,mcmf.t,d,0);
    114             if(d<0) mcmf.addedge(mcmf.s,i,-d,0);
    115         }
    116         if(!hasAns)
    117         {
    118             printf("-1
    ");
    119             continue;
    120         }
    121         if(all_d_is_zero)
    122         {
    123             printf("%d
    ",sum);
    124             continue;
    125         }
    126         
    127         printf("%d
    ",mcmf.mincost()+sum);
    128     }
    129 }

    (之前2713用STL超时,搞得这题也不敢用STL,继续数组模拟邻接表,然后最大边数MAXM没开好,RE两次、TLE一次……)

  • 相关阅读:
    Jquery操作表单Select元素常用方法
    NBear视频教程下载
    JSDT jQuery 自动完成功能设置
    JQuery插件收藏
    IE 性能分析工具
    Zend Studio for Eclipse 6.1与Spket整合进行Extjs开发
    英语中最常见的一百个词根
    MFC对话框背景色的设置
    防止屏幕闪烁
    MFC定时器
  • 原文地址:https://www.cnblogs.com/dilthey/p/7426089.html
Copyright © 2011-2022 走看看