My Brute (hdu 3315 二分图最大权匹配KM算法)

来源:互联网 发布:爱家房产源码 编辑:程序博客网 时间:2024/06/05 08:23

My Brute

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 951    Accepted Submission(s): 377


Problem Description
Seaco is a beautiful girl and likes play a game called “My Brute”. Before Valentine’s Day, starvae and xingxing ask seaco if she wants to spend the Valentine’s Day with them, but seaco only can spend it with one of them. It’s hard to choose from the two excellent boys. So there will be a competition between starvae and xingxing. The competition is like the game “My Brute”.


Now starvae have n brutes named from S1 to Sn and xingxing’s brutes are named from X1 to Xn. A competition consists of n games. At the beginning, starvae's brute Si must versus xingxin
’s brute Xi. But it’s hard for starvae to win the competition, so starvae can change his brutes’ order to win more games. For the starvae’s brute Si, if it wins the game, starvae can get Vi scores, but if it loses the game, starvae will lose Vi scores. Before the competition, starvae’s score is 0. Each brute can only play one game. After n games, if starvae’s score is larger than 0, we say starvae win the competition, otherwise starvae lose it. 

It’s your time to help starvae change the brutes’ order to make starvae’s final score be the largest. If there are multiple orders, you should choose the one whose order changes the least from the original one. The original order is S1, S2, S3 … Sn-1, Sn, while the final order is up to you.

For starvae’s brute Si (maybe this brute is not the original brute Si, it is the ith brute after you ordered them) and xingxing’s brute Xi, at first Si has Hi HP and Xi has Pi HP, Si’s damage is Ai and Xi’s is Bi, in other words, if Si attacks, Xi will lose Ai HP and if Xi attacks, Si will lose Bi HP, Si attacks first, then it’s Xi’s turn, then Si… until one of them’s HP is less than 0 or equal to 0, that, it lose the game, and the other win the game.

Come on, starvae’s happiness is in your hand!
 

Input
First line is a number n. (1<=n<=90) Then follows a line with n numbers mean V1 to Vn. (0<Vi<1000) Then follows a line with n numbers mean H1 to Hn. (1<=Hi<=100)Then follows a line with n numbers mean P1 to Pn. (1<=Pi<=100) Then follows a line with n numbers mean A1 to An.(1<=Ai<=50) Then follows a line with n numbers mean B1 to Bn. (1<=Bi<=50) A zero signals the end of input and this test case is not to be processed.
 

Output
For each test case, if starvae can win the competition, print the largest score starvae can get, and then follow a real percentage means the similarity between the original order and the final order you had changed, round it to three digits after the decimal point. If starvae can’t win the competition after changing the order, please just print “Oh, I lose my dear seaco!” Maybe the sample can help you get it.
 

Sample Input
34 5 66 8 1012 14 167 7 67 3 534 5 66 8 1012 14 165 5 55 5 50
 

Sample Output
7 33.333%Oh, I lose my dear seaco!
 

Author
starvae
 

Source
HDU “Valentines Day” Open Programming Contest 2010-02-14
 

Recommend
wxl   |   We have carefully selected several similar problems for you:  3395 2448 1565 3376 3313 


题意:starvae和xingxing各有n个英雄,starvae的每个英雄有血量Hi和攻击力Ai,xingxing的每个英雄有血量Pi和攻击力Bi,每轮比赛两人各出一个英雄i和j进行对抗,每次starvae的英雄i先攻击,则 j 会掉Ai的血,然后由j攻击,i掉Bj的血,谁的血先小于等于零就输了,若starvae赢了得v[i]的分,输了失v[i]的分,问最后starvae能得到的分的最大值是多少。

思路:这种题型是给出现有的匹配,求匹配的最大权值和改动的边数。若点数为N,则把每条边的权值扩大x倍(x>N),若是原有匹配,则再把权值加1。最后KM算法求出ans,则最大权值之和=ans/x,没有被改动的=ans%x。

代码:

#include <iostream>  #include <cstdio>  #include <cstring>  #include <algorithm>  #include <cmath>  #include <string>  #include <map>  #include <stack>  #include <vector>  #include <set>  #include <queue>  #pragma comment (linker,"/STACK:102400000,102400000")  #define mod 1000000009  #define INF 0x3f3f3f3f  #define pi acos(-1.0)  #define eps 1e-6  #define lson rt<<1,l,mid  #define rson rt<<1|1,mid+1,r  #define FRE(i,a,b)  for(i = a; i <= b; i++)  #define FREE(i,a,b) for(i = a; i >= b; i--)  #define FRL(i,a,b)  for(i = a; i < b; i++)  #define FRLL(i,a,b) for(i = a; i > b; i--)  #define mem(t, v)   memset ((t) , v, sizeof(t))  #define sf(n)       scanf("%d", &n)  #define sff(a,b)    scanf("%d %d", &a, &b)  #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)  #define pf          printf  #define DBG         pf("Hi\n")  typedef long long ll;  using namespace std;/*KM算法 O(nx*nx*ny)求最大权匹配(最佳匹配)若求最小权匹配,可将权值取相反数,结果取相反数点的标号从0开始*/const int N=110;struct ST{int a,b;}S[N],X[N];int nx,ny;      //两边的点数int g[N][N];    //二分图描述,g赋初值为-INFint linker[N],lx[N],ly[N];  //y 中各点匹配状态,x,y中的点的标号int slack[N];bool visx[N],visy[N];bool flag;bool DFS(int x){    visx[x]=true;    for (int y=0;y<ny;y++)    {        if (visy[y]) continue;        int tmp=lx[x]+ly[y]-g[x][y];        if (tmp==0)        {            visy[y]=true;            if (linker[y]==-1||DFS(linker[y]))            {                linker[y]=x;                return true;            }        }        else if (slack[y]>tmp)            slack[y]=tmp;    }    return false;}int KM(){    flag=true;    memset(linker,-1,sizeof(linker));    memset(ly,0,sizeof(ly));    for (int i=0;i<nx;i++) //赋初值,lx置为最大值    {        lx[i]=-INF;        for (int j=0;j<ny;j++)        {            if (g[i][j]>lx[i])                lx[i]=g[i][j];        }    }    for (int x=0;x<nx;x++)    {        for (int i=0;i<ny;i++)            slack[i]=INF;        while (true)        {            memset(visx,false,sizeof(visx));            memset(visy,false,sizeof(visy));            if (DFS(x)) break;            int d=INF;            for (int i=0;i<ny;i++)                if (!visy[i]&&d>slack[i])                    d=slack[i];            for (int i=0;i<nx;i++)                if (visx[i])                    lx[i]-=d;            for (int i=0;i<ny;i++)            {                if (visy[i])                    ly[i]+=d;                else                    slack[i]-=d;            }        }    }    int res=0;    for (int i=0;i<ny;i++)    {        if (linker[i]==-1||g[linker[i]][i]<=-INF) //有的点不能匹配的话return-1        {            flag=false;            break;        }        res+=g[linker[i]][i];    }    return res;}int n;int v[N];int main(){#ifndef ONLINE_JUDGE    freopen("C:/Users/asus1/Desktop/IN.txt","r",stdin);#endifint i,j;while (scanf("%d",&n),n){FRL(i,0,n) sf(v[i]);FRL(i,0,n) sf(S[i].a);FRL(i,0,n) sf(X[i].a);FRL(i,0,n) sf(S[i].b);FRL(i,0,n) sf(X[i].b);FRE(i,0,n)FRE(j,0,n) g[i][j]=-INF;nx=ny=n;FRL(i,0,n){FRL(j,0,n){int x=X[j].a/S[i].b+((X[j].a%S[i].b)==0?0:1);int y=S[i].a/X[j].b+((S[i].a%X[j].b)==0?0:1);if (x<=y)g[i][j]=v[i]*100;elseg[i][j]=-v[i]*100;if (i==j) g[i][j]++;}}int ans=KM();if (ans<=0) pf("Oh, I lose my dear seaco!\n");else{double aa= 1.0*(ans%100)/n * 100;pf("%d %.3lf%%\n",ans/100,aa);}}return 0;} 



1 0