poj3216 Repairing Company 二分匹配之最小路径覆盖+最短路

http://poj.org/problem?id=3216

题目说的是一个城市里面有Q个点,有M项工作,每个工作有个工作地点pi,最晚开始时间ti,和工作需要的时间di.
从城市中的任意一个点到另一个点的直接时间又一个矩阵给出。不连通为-1.注意间接联通是被允许的。
我再这个题上哉了2次,汗啊。我总是以为二分图的顶点时基于城市中的点的,但实际上时基于工作。

这一题首先对给定的图做一次floyd,这样就能求出两个点之间最少需要走的时间。
然后判断两个工作之间是否存在先后关系
最后做最小路径覆盖即可。注意这里的顶点数应该是工作数!这一题值得重点注意!!!

Source Code

Problem: 3216   User: 541780774
Memory: 440K   Time: 79MS
Language: G++   Result: Accepted


Source Code

 #include<stdio.h>   #include<stdlib.h>   #include<string.h>      int nx, ny,p[21][21];             // X的點數目、Y的點數目    int mx[201], my[201];   // X各點的配對對象、Y各點的配對對象    bool vy[201];           // 紀錄Graph Traversal拜訪過的點    bool adj[201][201];     // 精簡過的adjacency matrix       // 以DFS建立一棵交錯樹    bool DFS(int x)    {        for (int y=0; y<ny; ++y)            if (adj[x][y] && !vy[y])            {                vy[y] = true;                   // 找到擴充路徑                  if (my[y] == -1 || DFS(my[y]))                {                   mx[x] = y; my[y] = x;                   return true;                   }            }        return false;    }       int bipartite_matching()    {        // 全部的點初始化為未匹配點。        memset(mx, -1, sizeof(mx));           memset(my, -1, sizeof(my));           // 依序把X中的每一個點作為擴充路徑的端點,        // 並嘗試尋找擴充路徑。        int c = 0;        for (int x=0; x<nx; ++x)   //     if (mx[x] == -1)    // x為未匹配點,這行可精簡。            {                // 開始Graph Traversal                memset(vy, false, sizeof(vy));                if (DFS(x)) c++;            }        return c;    }   void Floyd(int n)   {           int i,j,k;           for(k=0;k<n;k++)           for(i=0;i<n;i++)           for(j=0;j<n;j++)           {              if((p[i][j]>p[i][k]+p[k][j]||p[i][j]==-1)&&i!=j&&p[i][k]!=-1&&p[k][j]!=-1)               p[i][j]=p[i][k]+p[k][j];           }      }              main()   {            int i,j,Q,M;            struct{                   int a;                   int b;                   int c;                   }h[201];            while(scanf("%d%d",&Q,&M),Q!=0&&M!=0)            {              memset(adj,0,sizeof(adj));              for(i=0;i<Q;i++)              for(j=0;j<Q;j++)                scanf("%d",&p[i][j]);               Floyd(Q);              for(i=0;i<M;i++)              {                scanf("%d%d%d",&h[i].a,&h[i].b,&h[i].c);                h[i].c=h[i].b+h[i].c;              }               for(i=0;i<M;i++)              for(j=0;j<M;j++)              {                if(h[i].c>h[j].b||p[h[i].a-1][h[j].a-1]==-1||i==j)                 continue;                else if(h[i].a==h[j].a)                 adj[i][j]=1;                else if(h[i].c+p[h[i].a-1][h[j].a-1]<=h[j].b)                 adj[i][j]=1;              }              nx=ny=M;                            printf("%d\n",M-bipartite_matching());                                                      }            system("pause");   }       
posted @ 2011-02-10 18:07  CoderZhuang  阅读(214)  评论(0编辑  收藏  举报