SPOJ GREED - Greedy island(费用流)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37943488/article/details/81543783

GREED - Greedy island

#max-flow #minimum-cost-flow

Gon is on Greedy island. He wants to go home. But to get the ticket to leave the game, he has to get N cards labeled in a sequence from 1 to N (the order of the cards in his hand is irrelevant). He already has N cards, but not forming a sequence from 1 to N. So he wants you to help him. For some cards, he can change one card for another for one piece of gold. Help him to get the ticket at the minimum cost (using the minimum number of exchanges).

Input

The first line contains t, the number of tests (1<=t<=10). For each test case:

  • the number of cards N is given is given in the first line (2<=N<=500).
  • the next N lines contain the N cards owned by Gon.
  • the following line contains e, the number of different allowed types of exchanges.
  • the next e lines contain two integers xi,yi each which mean that we can exchange and replace the card marked x by the card marked y and vice versa.

There is a blank line after each test case.

Output

For each test case, output a line denoting the minimum required cost.

Example

Input:
1
4
1
2
2
2
2
2 3
3 4

Output:
3

题目大意:一个人有一副牌,牌上的数字是1-n任意的数字,有几种变换,可以将一种牌变成某种牌,每一次变换要1块钱,问最少要多少钱才能将牌变为1-n

我就试着建了一下图就过了....

我的建图方法是记录当前这个人有的牌的数量,然后对于这些牌数不为0的牌,我们用源点连向它,容量为牌数费用为0,表示当前有多少张这样的牌,将1-n都连上汇点,容量为1,费用为0,表示这张牌只能有一张,对于能变换的,就连一条容量为无穷费用为1的边就行了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=510;
const int maxm=100010;
const int inf=0x3f3f3f3f;
struct Node
{
    int to;
    int capa;
    int cost;
    int next;
}edge[maxm];
int cnt;
int source,sink;
int head[maxn];
int num[maxn];
int dis[maxn];
int rec[maxn];
int pre[maxn];
bool vis[maxn];
void init()
{
    memset(head,-1,sizeof(head));
    memset(num,0,sizeof(num));
    cnt=0;
}
void add(int u,int v,int capa,int cost)
{
    edge[cnt].to=v;
    edge[cnt].capa=capa;
    edge[cnt].cost=cost;
    edge[cnt].next=head[u];
    head[u]=cnt++;
    edge[cnt].to=u;
    edge[cnt].capa=0;
    edge[cnt].cost=-cost;
    edge[cnt].next=head[v];
    head[v]=cnt++;
    return;
}
bool spfa()
{
    memset(dis,inf,sizeof(dis));
    memset(vis,false,sizeof(vis));
    memset(rec,-1,sizeof(rec));
    memset(pre,-1,sizeof(pre));
    queue<int> que;
    que.push(source);
    dis[source]=0;
    vis[source]=true;
    while(!que.empty())
    {
        int node=que.front();
        que.pop();
        vis[node]=false;
        for(int i=head[node];~i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(edge[i].capa>0&&dis[v]>dis[node]+edge[i].cost)
            {
                dis[v]=dis[node]+edge[i].cost;
                rec[v]=i;
                pre[v]=node;
                if(!vis[v])
                {
                    vis[v]=true;
                    que.push(v);
                }
            }
        }
    }
    return dis[sink]!=inf;
}
int mcmf()
{
    int maxflow=0;
    int mincost=0;
    while(spfa())
    {
        int flow=inf;
        int node=sink;
        while(node!=source)
        {
            flow=min(flow,edge[rec[node]].capa);
            node=pre[node];
        }
        maxflow+=flow;
        node=sink;
        while(node!=source)
        {
            mincost+=flow*edge[rec[node]].cost;
            edge[rec[node]].capa-=flow;
            edge[rec[node]^1].capa+=flow;
            node=pre[node];
        }
    }
    return mincost;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int test;
    scanf("%d",&test);
    while(test--)
    {
        init();
        int n;
        scanf("%d",&n);
        source=0;
        sink=n+1;
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            num[x]++;
        }
        for(int i=1;i<=n;i++)
        {
            if(num[i])
            {
                add(source,i,num[i],0);
            }
            add(i,sink,1,0);
        }
        int m;
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v,inf,1);
            add(v,u,inf,1);
        }
        printf("%d\n",mcmf());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37943488/article/details/81543783