首页 > 代码库 > 【UOJ 80】 二分图最大权匹配

【UOJ 80】 二分图最大权匹配

 

技术分享

 

【分析】

  之前打的那种KM会TLE。。。

  why??明明说n^3的啊?

 

技术分享
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxn 410
  9 #define Maxm 160010
 10 // #define INF 0x7fffffff
 11 #define LL long long
 12 const LL INF=1LL<<62;
 13 
 14 LL mymin(LL x,LL y) {return x<y?x:y;}
 15 LL mymax(LL x,LL y) {return x>y?x:y;}
 16 
 17 int N;
 18 
 19 int n,m;
 20 int match[Maxn],op[Maxn];
 21 LL eg[Maxn][Maxn],lx[Maxn],ly[Maxn],slack[Maxn];
 22 int visx[Maxn],visy[Maxn],pre[Maxn];
 23 
 24 void mh(int y)
 25 {
 26     for(int x,z;y>0;y=z)
 27     {
 28         x=pre[y];z=op[x];
 29         op[x]=y;match[y]=x;
 30     }
 31 }
 32 
 33 int nt;
 34 void ffind(int st)
 35 {
 36     for(int i=1;i<=N;i++) slack[i]=INF;
 37     queue<int> q;nt++;
 38     q.push(st);visx[st]=nt;
 39     while (1)
 40     {
 41         while(!q.empty())
 42         {
 43             int x=q.front();q.pop();
 44             for(int y=1;y<=N;y++)
 45              if(visy[y]!=nt)
 46              {
 47                  if(lx[x]+ly[y]==eg[x][y])
 48                  {
 49                      pre[y]=x;
 50                      if(!match[y]) {mh(y);return;}
 51                      q.push(match[y]);
 52                      visx[match[y]]=nt;visy[y]=nt;
 53                  }
 54                  else if(slack[y]>lx[x]+ly[y]-eg[x][y]) 
 55                     slack[y]=lx[x]+ly[y]-eg[x][y],pre[y]=x;
 56              }
 57         }
 58         LL delta=INF;
 59         for(int y=1;y<=N;y++) if(visy[y]!=nt) delta=mymin(delta,slack[y]);
 60         for(int i=1;i<=N;i++)
 61         {
 62             if(visx[i]==nt) lx[i]-=delta;
 63             if(visy[i]==nt) ly[i]+=delta;
 64             else slack[i]-=delta;
 65         }
 66         for(int i=1;i<=N;i++) if(visy[i]!=nt&&slack[i]==0)
 67         {
 68             if(!match[i]) {mh(i);return;}
 69             q.push(match[i]);
 70             visx[match[i]]=nt;visy[i]=nt;
 71         }
 72     }
 73 }
 74 
 75 
 76 LL KM()
 77 {
 78     memset(visx,0,sizeof(visx));
 79     memset(visy,0,sizeof(visy));
 80     for (int i=1;i<=N;i++) lx[i]=ly[i]=0,op[i]=match[i]=0;
 81     for (int i=1;i<=N;i++)
 82      for (int j=1;j<=N;j++)
 83       lx[i]=mymax(lx[i],eg[i][j]);
 84     for (int i=1;i<=N;i++) ffind(i);
 85 }
 86 
 87 void output()
 88 {
 89     LL ans=0;
 90     for(int i=1;i<=N;i++) ans+=lx[i]+ly[i];
 91     printf("%lld\n",ans);
 92     for(int i=1;i<=n;i++) if(eg[i][op[i]]!=0) printf("%d ",op[i]);
 93     else printf("0 ");printf("\n");
 94 }
 95 
 96 void init()
 97 {
 98     int l;
 99     memset(eg,0,sizeof(eg));
100     scanf("%d%d%d",&n,&m,&l);
101     for(int i=1;i<=l;i++)
102     {
103         int x,y;
104         LL c;
105         scanf("%d%d%lld",&x,&y,&c);
106         eg[x][y]=mymax(eg[x][y],c);
107     }
108     N=mymax(n,m);
109 }
110 
111 int main()
112 {
113     init();
114         KM();
115     output();
116         return 0;
117 }
View Code

 

【UOJ 80】 二分图最大权匹配