zoukankan      html  css  js  c++  java
  • 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");   }       
  • 相关阅读:
    【Lintcode】112.Remove Duplicates from Sorted List
    【Lintcode】087.Remove Node in Binary Search Tree
    【Lintcode】011.Search Range in Binary Search Tree
    【Lintcode】095.Validate Binary Search Tree
    【Lintcode】069.Binary Tree Level Order Traversal
    【Lintcode】088.Lowest Common Ancestor
    【Lintcode】094.Binary Tree Maximum Path Sum
    【算法总结】二叉树
    库(静态库和动态库)
    从尾到头打印链表
  • 原文地址:https://www.cnblogs.com/zxj015/p/2740291.html
Copyright © 2011-2022 走看看