POJ3216 最小路径覆盖

    首先说一下题意,Q个区域,M个任务,每个区域任务可能有多个,然后给你个到各地所需时间的矩阵,每个任务都有开始和持续时间,问最少需要多少工人? 每个工人只能同时执行一个任务。

通过题意,我的瞬间反应就是先把点拆开再说,因为每个区域可能有多个任务,所以把每个任务都当做一点处理,之后就需要考虑一件事情,一个工人在Qi区域做完之后是不是应该去一个离他最近且正好有任务的地方Qj,那么他从Qi到Qj是不是应该走最近的路线? 下一步就出来了,求出所有区域之间的最短距离,用floyd一键搞定。然后就可以建图(有向的)了,把能衔接起来的任务统统连上,按照上一个任务的开始时间+持续时间+到下一点的时间<=下一点的开始时间来连边(不用换区域的到下一点的时间为零),那么此时的问题就变成了多少个工人能把图走完?  即最小路径覆盖,直接匈牙利算法搞定。

   好了上代码

  1 #include<cstdio>            

  2 #include<cstring>

  3 #include<iostream>

  4 #include<vector>

  5 #define maxn 500

  6 #define inf 0xfffffff

  7 using namespace std;

  8 

  9 struct edge

 10 {

 11     int pos,realpos,start,need;

 12 }rela[maxn];

 13 vector<int> q[maxn];

 14 int mize[maxn][maxn],point[maxn];

 15 int vis[maxn],link[maxn];

 16 int n,m,sum;

 17 void init()

 18 {

 19     for(int i=0;i<=maxn;i++)

 20         q[i].clear();

 21     memset(rela,0,sizeof(rela));

 22     memset(mize,0,sizeof(mize));

 23     memset(point,0,sizeof(point));

 24     for(int a=1;a<=n;a++)

 25         for(int b=1;b<=n;b++)

 26         {

 27             scanf("%d",&mize[a][b]);

 28             if(mize[a][b]==-1) mize[a][b]=inf;

 29         }

 30 

 31     for(int c=1;c<=m;c++)

 32     {

 33         scanf("%d %d %d",&rela[c].pos,&rela[c].start,&rela[c].need);

 34         int p=0;

 35         for(int d=1;d<c;d++)

 36         {

 37             if(rela[d].pos==rela[c].pos) p++;

 38         }

 39         rela[c].realpos=rela[c].pos+n*p;

 40         point[rela[c].realpos]=1;

 41         if(sum<rela[c].realpos) sum=rela[c].realpos;

 42     }

 43 }

 44 void floyd()

 45 {

 46     for(int i=1;i<=n;i++)

 47     {

 48         for(int j=1;j<=n;j++)

 49         {

 50            for(int k=1;k<=n;k++)

 51            {

 52                mize[j][k]=mize[j][k]<mize[i][k]+mize[j][i]?mize[j][k]:mize[i][k]+mize[j][i];

 53            }

 54         }

 55     }

 56 

 57 

 58 }

 59 void set_map()

 60 {

 61     for(int i=1;i<=m;i++)

 62     {

 63         int realpos=rela[i].realpos,pos=rela[i].pos,time=rela[i].need+rela[i].start;

 64         for(int j=1;j<=m;j++)

 65         {

 66             if(j==i) continue;

 67             int a=rela[j].realpos,b=rela[j].pos,t=rela[j].start;

 68      //       if(mize[pos][b]==-1||mize[b][pos]==-1) continue;

 69             if(time+mize[pos][b]<=t)     // 矩阵式对称的  怎么写都无所谓

 70             {

 71                 q[realpos].push_back(a);

 72            //     q[a].push_back(realpos);

 73             }

 74         }

 75     }

 76  /*   for(int i=1;i<=8;i++)

 77     {

 78         if(q[i].size()==0) continue;

 79         cout<<i<<": "<<endl;

 80         for(int j=0;j<q[i].size();j++)

 81         {

 82             cout<<q[i][j]<<" ";

 83         }

 84         cout<<endl;

 85     }*/

 86 }

 87 int dfs(int x)

 88 {

 89     for(int i=0;i<q[x].size();i++)

 90     {

 91           int y=q[x][i];

 92           if(!vis[y])

 93           {

 94               vis[y] = true;

 95              if(link[y]== -1||dfs(link[y]))

 96              {

 97                   link[y] = x;

 98                   return true;

 99              }

100           }

101     }

102     return false;

103 }

104 void solve()

105 {

106     int s=0;

107     memset(link,-1,sizeof(link));

108     for(int i=1;i<=sum;i++)

109     {

110         if(point[i]==0) continue;

111         memset(vis,0,sizeof(vis));

112         if(dfs(i)) s++;

113     }

114     printf("%d\n",m-s);

115 }

116 int main()

117 {

118     while(scanf("%d%d",&n,&m)!=EOF)

119     {

120         if(n==0&&m==0) break;

121         sum=0;

122         init();

123         floyd();

124         set_map();

125         solve();

126     }

127     return 0;

128 }
View Code

 

你可能感兴趣的:(poj)