CodeChef - SPCLN Cleaning the Space(最小割,好题)

题目链接

SPCLN: 太空清扫 题目描述

一架宇宙飞船准备要穿过一条长长的星际隧道。隧道由 N 个静止的太空碎片组成。为了成功 地完成任务,飞船需要摧毁所有太空碎片。飞船的控制单元由 M 个按钮组成,这些按钮可以被用 来摧毁太空碎片。按下某个特定的按钮可能造成某些(也许多个)太空碎片被摧毁。一旦一个太 空碎片被摧毁,其质量将被转换成能量,这些能量将最终被飞船所吸收以提高其速度。一个特定 碎片被摧毁所释放的能量与被用来摧毁它的按钮有关。我们定义一个能量矩阵 E,对于每个碎片 i 和按钮 j,E[i][j](0 ≤ E[i][j] ≤ 100) 表示用按钮 j 摧毁碎片 i 所释放的能量。若 E[i][j] = −1 表 示碎片 i 不能被按钮 j 摧毁。

一些碎片的摧毁有依赖关系。飞船必须在摧毁某些碎片前先将另一些碎片摧毁。这里一共有 K 组依赖关系。每组依赖关系包含两个用空格隔开的整数 i 和 j,表示碎片 i 的摧毁必须发生在碎 片 j 的摧毁之前。

每一个按钮只能被按下一次,而且必须按照 1 ∼ M 的顺序按下(如按钮 2 不能在按钮 1 前被 按下)。当按下一个按钮时,我们定义“目标向量”为一个长为 N 的二进制字符串 T 。对于碎片 i,若 T [i] 为 1,表示你希望用这个按钮去摧毁碎片 i,否则 T [i] 为 0。当按钮被按下时,所有在目 标向量中出现过的碎片将同时被摧毁。

飞船可以用某个按钮摧毁任意数量的碎片,包括 0 个,只要它们能被这个按钮摧毁,并满足 依赖关系。

  现在你的任务是计算飞船通过这条隧道所能获得的最大平均能量。

输入格式

输入第一行包括两个用空格隔开的整数 N 和 M。
接下来 N 行,每行 M 个整数,表示 E[i][j]。
接下来一行包含一个整数 K。
接下来 K 行,每行包含两个用空格隔开的整数 u 和 v(u ̸= v),表示碎片 u 必须在碎片 v 前

被摧毁。

输出格式

  输出一个实数表示最大平均能量,请四舍五入保留小数点后两位。

数据范围与约定

• 1 ≤ M, N ≤ 100
• 0≤K≤100
• −1≤E[i][j]≤100
• 1≤u,v≤N
• 数据保证存在摧毁所有碎片的方案。

样例数据

输入

3 3
10 70 100 

80 50 40

80 20 40

2
1 2

1 3

输出

50.00

样例解释

  唯一的摧毁所有碎片的方案为:用第二个按钮摧毁第一个碎片,用第三个按钮摧毁第二个和
第三个碎片。

平均能量为 (70 + 40 + 40)/3 = 50.00。 

 

题解:这题问了qls才知道怎么做的。

因为题目说了要摧毁所有的碎片,所以就是最大化能量总和。

这样建图:对于每个碎片拆成m+1个点,第i个碎片的第j个点向第j+1个点连一条100-E[i][j]的边,对于k个限制条件,如果碎片u要在碎片v之前被摧毁,那么碎片u的第j个点向第j+1个点连容量为inf的边,然后源点s向每个碎片的第一个点连一条容量为inf的边,每个碎片的最后一点向汇端t连一条容量为inf的边,然后跑一遍s-t的最小割,记最小割为ans,用(100*n-ans)/n即为答案

神建图!

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
const int maxn=11000;
const int maxm=100500;
struct Node
{
    int from,to,next;
    int cap;
}edge[maxm];
int tol;
int dep[maxn];
int head[maxn];
void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)//第一条边下标必须为偶数
{
    edge[tol].from=u;edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];head[u]=tol++;
    edge[tol].from=v;edge[tol].to=u;edge[tol].cap=0;edge[tol].next=head[v];head[v]=tol++;
}
int BFS(int start,int end)
{
    int que[maxn];
    int front,rear;
    front=rear=0;
    memset(dep,-1,sizeof(dep));
    que[rear++]=start;
    dep[start]=0;
    while(front!=rear)
    {
        int u=que[front++];
        if(front==maxn)front=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(edge[i].cap>0&&dep[v]==-1)
            {
                dep[v]=dep[u]+1;
                que[rear++]=v;
                if(rear>=maxn)rear=0;
                if(v==end)return 1;
            }
        }
    }
    return 0;
}
int a[110][110];
int dinic(int start,int end)
{
    int res=0;
    int top;
    int stack[maxn];
    int cur[maxn];
    while(BFS(start,end))
    {
        memcpy(cur,head,sizeof(head));
        int u=start;
        top=0;
        while(1)
        {
            if(u==end)
            {
                int min=inf;
                int loc;
                for(int i=0;i<top;i++)
                    if(min>edge[stack[i]].cap)
                    {
                        min=edge[stack[i]].cap;
                        loc=i;
                    }
                for(int i=0;i<top;i++)
                {
                    edge[stack[i]].cap-=min;
                    edge[stack[i]^1].cap+=min;
                }
                res+=min;
                top=loc;
                u=edge[stack[top]].from;
            }
            for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)
                if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])
                    break;
            if(cur[u]!=-1)
            {
                stack[top++]=cur[u];
                u=edge[cur[u]].to;
            }
            else
            {
                if(top==0)break;
                dep[u]=-1;
                u=edge[stack[--top]].from;
            }
        }
    }
    return res;
}
int main()
{
    int n,m,k;
    scanf("%d%d",&n,&m);
    init();
    int st=0,ed=n*(m+1)+1;
    rep(i,1,n+1) rep(j,1,m+1) scanf("%d",&a[i][j]);
    rep(i,1,n+1) rep(j,1,m+1) addedge((m+1)*(i-1)+j,(m+1)*(i-1)+j+1,100-a[i][j]);
    rep(i,1,n+1) addedge(st,(i-1)*(m+1)+1,inf),addedge(i*(m+1),ed,inf);
    scanf("%d",&k);
    rep(i,1,k+1)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        rep(j,1,m+1)
            addedge((u-1)*(m+1)+j,(v-1)*(m+1)+j+1,inf);
    }
    printf("%.2lf\n",1.0*(100*n-dinic(st,ed))/n);
    return 0;
}

 

posted @ 2017-07-30 10:17  tarjan's  阅读(159)  评论(0编辑  收藏  举报