HDU5383 不需要满流的费用流 网络流

建立二分图,然后

可以建立二分图,把Tuner Monster视为二分图左侧的点,Non-Tunner Monster视为二分图右侧的点。

计算出两两能配成的最高攻击力后连边,利用费用流计算。

建图:点规模O(n)O(n),边规模O(n^2)O(n2)

谢谢@FZ

另外不需要满流,把每次的费用求一个min就行了

题解:



/*
 * Author:  Praesidio
 * Created Time:  2015/8/13 19:08:51
 * File Name: fuck.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<utility>

using namespace std;

#define M0(x) memset(x, 0, sizeof(x))
#define MINF(x) memset(x, 0x77, sizeof(x))
#define MNE(x) memset(x, 0xff, sizeof(x))
#define PB push_back
#define SZ(v) ((int)(v).size())
#define rep(i, n) for(int i = 0; i < (n); i ++)
#define repf(i, a, b) for(int i = (a); i <= (b); i ++)
#define repd(i, a, b) for(int i = (a); i >= (b); i --)
#define out(x) cout<<#x<<":"<<(x)<<" "
#define test cout<<"fuck!!!"<<endl
#define newl cout<<endl
#define tst(a) cout<<#a<<endl
#define CINBEQUICKER std::ios::sync_with_stdio(false)

typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<double> VD;
typedef long long int64;

const double eps = 1e-8;
const double PI = atan(1.0)*4;
const int INF = 2139062143;

const int maxn = 330;

struct Monster {
    int type , level , attack;
    Monster(){}
    Monster(int type,int level,int attack):type(type),level(level),attack(attack){}
    void in() {
        scanf("%d %d %d",&type,&level,&attack);
    }
};
Monster mon[maxn];
int n , m;

struct Edge {
    int from , to , cap , flow , cost;
};

struct MCMF {
    int n , m , s , t;
    vector<Edge> edges;
    vector<int> G[maxn];
    int inq[maxn] , d[maxn] , p[maxn] , a[maxn];
    void init( int n ) {
        this->n = n;
        for ( int i = 0 ; i < n ; i++ ) G[i].clear();
        edges.clear();
    }
    void addedge ( int from , int to , int cost ) {
        edges.push_back ( (Edge) { from , to , 1 , 0 , -cost } );
        edges.push_back ( (Edge) { to , from , 0 , 0 , cost } );
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    void addedgee ( int from , int to , int cap , int cost ) {
        edges.push_back ( (Edge) { from , to , cap , 0 , -cost } );
        edges.push_back ( (Edge) { to , from , 0 , 0 , cost } );
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    bool spfa ( int s , int t , int &flow , int& cost, int &ans) {
        for ( int i = 0 ; i < n ; i++ ) d[i] = INF;
        memset ( inq , 0 , sizeof ( inq ) );
        d[s] = 0 ; inq[s] = 1 ; p[s] = 0 ; a[s] = INF;
        queue<int> Q;
        Q.push(s);
        while ( !Q.empty() ) {
            int u = Q.front(); Q.pop();
            inq[u] = 0;
            for ( int i = 0 ; i < (int)G[u].size() ; i++ ) {
                Edge& e = edges[G[u][i]];
                if ( e.cap > e.flow && d[e.to] > d[u] + e.cost ) {
                    d[e.to] = d[u] + e.cost;
                    p[e.to] = G[u][i];
                    a[e.to] = min ( a[u] , e.cap - e.flow );
                    if ( !inq[e.to] ) { Q.push(e.to); inq[e.to] = 1; }
                }
            }
        }
        if ( d[t] == INF ) return false;
        flow += a[t];
        cost += d[t] * a[t];
        int u = t;
        while ( u != s ) {
            edges[p[u]].flow += a[t];
            edges[p[u]^1].flow -= a[t];
            u = edges[p[u]].from;
        }
        ans=min(ans,cost);//??不需要满流
       //cout << flow << " " << cost << endl;
        return true;
    }
    int Mincost ( int s , int t ) {
       int flow = 0 , cost = 0,ans=INF;
       while ( spfa( s , t , flow , cost ,ans) );
       //cout << flow << " " << cost << endl;
       if (ans==INF) ans=0;
       cost=ans;
       return cost;
    }

    int gao ( int n ) {
        int ret = 0;
        for ( int i = 0 ; i < (int)G[0].size() ; i++ ) {
            Edge e = edges[G[0][i]];
            if ( e.flow == 0 ) {
                cout << "#" << e.to << endl;
                ret += mon[e.to].attack;
            }
        }
        for ( int i = 0 ; i < (int)G[n+1].size() ; i++ ) {
            Edge e = edges[G[n+1][i]^1];
            cout << e.from << " " << e.flow << endl;
            if ( e.flow == 0 ) {
                cout << "#" << e.from << endl;
                ret += mon[e.from].attack;
            }
        }
        return ret;
    }
};

MCMF solve;

#define addedge solve.addedge

int g[maxn][maxn];

int main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    //std::ios::sync_with_stdio(false);

    int T;
    scanf("%d",&T);
    while ( T-- ) {
        scanf("%d%d",&n,&m);

        memset ( g , -1 , sizeof(g) );

        int sum0 = 0 , sum1 = 0;
        for ( int i = 1 ; i <= n ; i++ ) {
            mon[i].in();
            if ( mon[i].type == 0 ) sum0++;
            else sum1++;
        }

        
        
        //solve.init ( n + 2 + ( (sum0==sum1)?0:1 ) );
        solve.init(n+2);

        
        for ( int i = 1 ; i <= n ; i++ ) {
            if ( mon[i].type == 0 ) {
                addedge ( 0 , i , 0 );
            }
            else {
                addedge ( i , n + 1 , 0 );
            }
             if ( mon[i].type == 0 ) addedge(i,n+1,mon[i].attack); //??
            else addedge(0,i,mon[i].attack);
        }

        //useful
        //if ( sum0 > sum1 ) {
            //solve.addedgee ( n + 2 , n + 1 , sum0-sum1 , 0 );
            //for ( int i = 1 ; i <= n ; i++ ) {
                //if ( mon[i].type == 0 ) {
                    //addedge ( i , n + 2 , mon[i].attack );
                //}
            //}
        //}
        //else if ( sum0 < sum1 ) {
            //solve.addedgee ( 0 , n + 2 , sum1 - sum0 , 0 );
            //for ( int i = 1 ; i <= n ; i++ ) {
                //if ( mon[i].type == 1 ) {
                    //addedge ( n + 2 , i , mon[i].attack );
                //}
            //}
        //}
        
        for ( int i = 1 ; i <= n ; i++ ) {
            for ( int j = 1 ; j <= n ; j++ ) {
                if ( mon[i].type == 0 && mon[j].type == 1 ) {
//                    addedge ( i , j , mon[i].attack + mon[j].attack );
                    g[i][j] = max ( g[i][j] , mon[i].attack + mon[j].attack );
                }
            }
        }
        
        while ( m-- ) {
            int level , attack , need;
            scanf("%d %d %d",&level,&attack,&need);
            if ( need == 0 ) {
                for ( int i = 1 ; i <= n ; i++ ) {
                    for ( int j = 1 ; j <= n ; j++ ) {
                        if ( i == j ) continue;
                        if ( mon[i].type == 0 && mon[j].type == 1 && mon[i].level + mon[j].level == level ) {
//                            addedge ( i , j , attack );
                            g[i][j] = max ( g[i][j] , attack );
                        }
                    }
                }
            }
            else if ( need == 1 ) {
                int x;
                scanf("%d",&x);
                for ( int i = 1 ; i <= n ; i++ ) {
                    if ( mon[i].type == mon[x].type ) continue;
                    if ( mon[x].level + mon[i].level == level ) {
                        if ( mon[x].type == 0 ) g[x][i] = max ( g[x][i] , attack ); //addedge ( x , i , attack );
                        else g[i][x] = max ( g[i][x] , attack ); //addedge ( i , x , attack );
                    }
                }
            }
            else {
                int x , y;
                scanf("%d %d",&x,&y);
                if ( mon[x].type == 0 ) g[x][y] = max ( g[x][y] , attack ); //addedge( x , y , attack );
                else g[y][x] = max ( g[y][x] , attack );//addedge ( y , x , attack );
            }
        }
        
        for ( int i = 1 ; i <= n ; i++ ) {
            for ( int j = 1 ; j <= n ; j++ ) {
                if ( g[i][j] > -1 ) {
                    addedge ( i , j , g[i][j] );
                }
            }
        }

//#define edges solve.edges
//        for ( int i = 0 ; i < edges.size() ; i++ ) {
//            cout << edges[i].from << " " << edges[i].to << " " << edges[i].cap << " " << edges[i].flow << " " << edges[i].cost << endl;
//        }
//#undef edges
        int Ans = -solve.Mincost( 0 , n + 1 );
//        solve.gao( n );
        
        printf("%d\n",Ans);
    }
    return 0;
}


Yu-Gi-Oh!

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 360    Accepted Submission(s): 93


Problem Description
"Yu-Gi-Oh!", also known as "Dueling Monsters", is a popular trading card game which has nearly 20 years history. Next year, YGO will reach its 20th birthday.

Stilwell has  n  monsters on the desk, each monster has its  leveli  and  ATKi . There are two kinds of monsters, Tuner monsters and Non-Tuner monsters.

Now, Stilwell plans to finish some "Synchro Summon", and "Synchro Summon" is a kind of special summon following these rules (a little different from the standard YGO rules):

(1) A "Synchro Summon" needs two monsters as the material of this summon, and they must be one Tuner monster and one Non-Tuner monster.
In other words, we can cost one Tuner monster and one Non-Tuner monster to get a Synchro monster ("cost" means remove form the desk, "get" means put on to the desk).

(2) To simplify this problem, Synchro monsters are neither Tuner monsters nor Non-Tuner monsters.

(3) The level sum of two material must be equal to the level of Synchro monster we summon.
For example:
A Level 3 Tuner monster  +  A Level 2 Non-Tuner monster  =  A Level 5 Synchro Monster
A Level 2 Tuner monster  +  A Level 4 Non-Tuner monster  =  A Level 6 Synchro Monster
A Level 4 Tuner monster  +  A Level 4 Non-Tuner monster  =  A Level 8 Synchro Monster

(4) The material of some Synchro monster has some limits, the material must contain some specific monster.
For example:
A Level 5 Synchro Monster  α  requires A Level 3 Tuner monster  α  to be its material
A Level 6 Synchro Monster  β  requires A Level 4 Non-Tuner monster  β  to be its material
A Level 8 Synchro Monster  γ  requires A Level 4 Tuner monster  γ   +  A Level 4 Non-Tuner monster  γ  to be its material
A Level 5 Synchro Monster  φ  doesn't require any monsters to be its material
Then
A Level 3 Tuner monster  α   +  A Level 2 Non-Tuner monster  =  A Level 5 Synchro Monster  α
A Level 3 Tuner monster  δ   +  A Level 2 Non-Tuner monster   A Level 5 Synchro Monster  α
A Level 2 Tuner monster  +  A Level 4 Non-Tuner monster  β   =  A Level 6 Synchro Monster  β
A Level 3 Tuner monster  +  A Level 3 Non-Tuner monster  ζ    A Level 6 Synchro Monster  β
A Level 4 Tuner monster  γ   +  A Level 4 Non-Tuner monster  γ   =  A Level 8 Synchro Monster  γ
A Level 4 Tuner monster  σ   +  A Level 4 Non-Tuner monster  γ    A Level 8 Synchro Monster  γ
A Level 4 Tuner monster  γ   +  A Level 4 Non-Tuner monster  ϕ    A Level 8 Synchro Monster  γ
A Level 3 Tuner monster  +  A Level 2 Non-Tuner monster  =  A Level 5 Synchro Monster  φ
A Level 3 Tuner monster  α   +  A Level 2 Non-Tuner monster  =  A Level 5 Synchro Monster  φ

Stilwell has  m  kinds of Synchro Monster cards, the quantity of each Synchro Monster cards is infinity.

Now, given  leveli  and  ATKi  of every card on desk and every kind of Synchro Monster cards. Please finish some Synchro Summons (maybe zero) to maximum  ATKi  of the cards on desk.
 

Input
The first line of the input contains a single number  T , the number of test cases.

For each test case, the first line contains two integers  n m .

Next  n  lines, each line contains three integers  tuneri leveli , and  ATKi , describe a monster on the desk. If this monster is a Tuner monster, then  tuneri=1 , else  tuneri=0  for Non-Tuner monster.

Next  m  lines, each line contains integers  levelj ATKj rj , and following  rj  integers are the required material of this Synchro Monster (the integers given are the identifier of the required material).
The input data guarantees that the required material list is available, two Tuner monsters or two Non-Tuner monsters won't be required. If  ri=2  the level sum of two required material will be equal to the level of Synchro Monster.

T10 n,m300 1leveli12 0ATKi5000 0ri2
 

Output
T  lines, find the maximum  ATKi  after some Synchro Summons.
 

Sample Input
  
  
5 2 2 1 3 1300 0 2 900 5 2300 1 1 8 2500 0 2 1 1 3 1300 1 2 900 5 2300 1 1 3 1 1 3 1300 0 2 900 0 2 800 5 2300 1 1 3 1 1 1 233 0 1 233 0 1 200 2 466 2 1 2 6 3 1 3 1300 0 2 900 0 5 1350 1 4 1800 0 10 4000 0 10 1237 5 2300 1 1 8 3000 0 6 2800 0
 

Sample Output
  
  
2300 2200 3200 666 11037
 

Author
SXYZ
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   5390  5389  5388  5387  5386 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值