CodeChef - RIN 最小割应用 规划问题
题意:给定\(n\)门课和\(m\)个学期,每门课在每个学期有不同的得分,需要选定一个学期去完成,但存在约束条件,共有\(k\)对课程需要\(a\)在\(b\)开始学前学会,求最大得分(原问题是求最高平均得分)
把问题转换为最小损失得分,那么可以用最小割来求解
\(Y[i][j]\)为第\(i\)门课在\(j\)学期损失的学分,若不存在则设为正无穷
那么每一门课\(i\)都要拆\(m\)个点,表示为\((i,j)\),源\(S\)和\((i,1)\)的容量为\(Y[i][1]\),其他学期相互连边,容量为\(Y[i][j]\),
注意到汇点\(T\)时是\((i,m)\)到\(T\),边不可割,所以也为正无穷
前置课程需要保证\(b\)在第一学期不可能被割(正无穷边),且\(a\)被割都得在\(b\)被割的前面,即对于\(i>1\)的学期都要有\((a,i-1)\)到\((b,i)\)的边,容量为正无穷
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define iin(a) scanf("%d",&a)
#define lin(a) scanf("%lld",&a)
#define din(a) scanf("%lf",&a)
#define s0(a) scanf("%s",a)
#define s1(a) scanf("%s",a+1)
#define print(a) printf("%lld",(ll)a)
#define enter putchar('\n')
#define blank putchar(' ')
#define println(a) printf("%lld\n",(ll)a)
#define IOS ios::sync_with_stdio(0)
using namespace std;
const int MAXN = 1e6+11;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
typedef long long ll;
ll read(){
    ll x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],cap[MAXN<<1],flow[MAXN<<1];
int head[MAXN],tot;
void init(){
    memset(head,-1,sizeof head);
    tot=0;
}
void add(int u,int v,int w){
    to[tot]=v;
    nxt[tot]=head[u];
    cap[tot]=w;
    flow[tot]=0;
    head[u]=tot++;
    swap(u,v);
    to[tot]=v;
    nxt[tot]=head[u];
    cap[tot]=0;
    flow[tot]=0;
    head[u]=tot++;
}
int n,m,s,t;
int dis[MAXN],pre[MAXN],cur[MAXN],gap[MAXN];
bool vis[MAXN];
struct QUEUE{
    int que[MAXN];
    int front,rear;
    void init(){front=rear=0;}
    void push(int u){que[rear++]=u;}
    int pop(){return que[front++];}
    bool empty(){return front==rear;}
}que;
void bfs(){
    memset(vis,0,sizeof vis);
    que.init();
    que.push(t);
    vis[t]=1;dis[t]=0;
    while(que.empty()^1){
        int u = que.pop();
        for(int i = head[u]; ~i; i = nxt[i]){
            register int v=to[i],c=cap[i^1],f=flow[i^1];
            if(!vis[v]&&c>f){
                vis[v]=1;
                dis[v]=dis[u]+1;
                que.push(v);
            }
        }
    }
}
int aug(){
    int u=t,ans=INF;
    while(u!=s){
        ans=min(ans,cap[pre[u]]-flow[pre[u]]);
        u=to[pre[u]^1];
    }
    u=t;
    while(u!=s){
        flow[pre[u]]+=ans;
        flow[pre[u]^1]-=ans;
        u=to[pre[u]^1];
    }
    return ans;
}
int isap(){
    int ans=0;
    bfs();
    memset(gap,0,sizeof gap);
    memcpy(cur,head,sizeof head);
    for(int i = 1; i <= n; i++) gap[dis[i]]++;
    int u = s;
    while(dis[s]<n){
        if(u==t){
            ans+=aug();
            u=s;
        }
        bool ok=0;
        for(int i = cur[u]; ~i; i = nxt[i]){
            int v=to[i],c=cap[i],f=flow[i];
            if(c>f&&dis[u]==dis[v]+1){
                ok=1;
                pre[v]=i;
                cur[u]=i;
                u=v;
                break;
            }
        }
        if(!ok){
            int mn=n-1;
            for(int i = head[u]; ~i; i = nxt[i]){
                int v=to[i],c=cap[i],f=flow[i];
                if(c>f) mn=min(mn,dis[v]);
            }
            if(--gap[dis[u]]==0) break;
            dis[u]=mn+1;gap[dis[u]]++;cur[u]=head[u];
            if(u!=s) u=to[pre[u]^1];
        }
    }
    return ans;
}
int X[233][333],Y[233][333],id[233][333];
int A[233],B[333],k;
int main(){
    while(cin>>n>>m>>k){
        rep(i,1,n){
            rep(j,1,m){
                X[i][j]=read();
                Y[i][j]=(X[i][j]==-1?INF:(100-X[i][j]));
            }
        }
        rep(i,1,k){
            A[i]=read();
            B[i]=read();
        }
        s=n*m+1;t=n*m+2;
        init();int cnt=0;
        rep(i,1,n){
            id[i][1]=++cnt;
            add(s,id[i][1],Y[i][1]);
            rep(j,2,m){
                id[i][j]=++cnt;
                add(id[i][j-1],id[i][j],Y[i][j]);
            }
            add(id[i][m],t,INF);
        }
        rep(i,1,k){
            add(s,id[B[i]][1],INF);
            rep(j,2,m){
                add(id[A[i]][j-1],id[B[i]][j],INF);
            }
        }
        int r=n;
        n=n*m+2; //note
        ll ans=100*r-isap();
        printf("%.2lf\n",(double)ans/r);
    }
    return 0;
}
CodeChef - RIN 最小割应用 规划问题的更多相关文章
- Network Wars-ZOJ2676最小割+01规划
		Time Limit: 5 Seconds Memory Limit: 32768 KB Special Judge Network of Byteland consists of n servers ... 
- Codechef RIN 「Codechef14DEC」Course Selection  最小割离散变量模型
		问题描述 提供中文版本好评,一直以为 Rin 是题目名字... pdf submit 题解 参考了 东营市胜利第一中学姜志豪 的<网络流的一些建模方法>(2016年信息学奥林匹克中国国家队 ... 
- [CodeChef]RIN(最小割)
		Description 有m门课可以在n个学期内学习,第i门课在第j个学期的收益是\(X_{i,j}\),一个学期可以学多门课,有的课之间有依赖关系,即必须先学a再学b,求最大收益.n,m<= ... 
- ZOJ 2676 Network Wars ★(最小割算法介绍 && 01分数规划)
		[题意]给出一个带权无向图,求割集,且割集的平均边权最小. [分析] 先尝试着用更一般的形式重新叙述本问题.设向量w表示边的权值,令向量c=(1, 1, 1, --, 1)表示选边的代价,于是原问题等 ... 
- zoj 2676 Network Wars 0-1分数规划+最小割
		题目详解出自 论文 Amber-最小割模型在信息学竞赛中的应用 题目大意: 给出一个带权无向图 G = (V,E), 每条边 e属于E都有一个权值We,求一个割边集C,使得该割边集的平均边权最小,即最 ... 
- 【BZOJ3232】圈地游戏 分数规划+最小割
		[BZOJ3232]圈地游戏 Description DZY家的后院有一块地,由N行M列的方格组成,格子内种的菜有一定的价值,并且每一条单位长度的格线有一定的费用. DZY喜欢在地里散步.他总是从任意 ... 
- bzoj 3232: 圈地游戏【分数规划+最小割】
		数组开小导致TTTTTLE-- 是分数规划,设sm为所有格子价值和,二分出mid之后,用最小割来判断,也就是判断sm-dinic()>=0 这个最小割比较像最大权闭合子图,建图是s像所有点连流量 ... 
- bzoj 3232 圈地游戏 —— 01分数规划+最小割建图(最大权闭合子图)
		题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3232 心烦意乱的时候调这道题真是...越调越气,就这样过了一晚上... 今天再认真看看,找出 ... 
- zoj  2676  二分+ISAP模板求实型参数的最小割(0-1分数规划问题)(可做ISAP模板)
		/* 参考博文:http://www.cnblogs.com/ylfdrib/archive/2010/09/01/1814478.html 以下题解为转载代码自己写的: zoj2676 胡伯涛论文& ... 
随机推荐
- Java  基于web service 暴露接口 供外部调用
			package cn.zr.out.outinterface; import java.text.SimpleDateFormat; import java.util.Date; import jav ... 
- Solidity 没名字的function(){...}作用
			官方解释: 这个叫做fallback function,当有人 1. 只发送以太币给合约而不带任何输入数据:2. 调用smart contract时调起了一个不存在的方法.会触发执行这个方法. Wha ... 
- Sublime Text notes
			1. 设置在窗口右下方显示文件的编码,在user preferences里加上以下的配置 2.设置用新标签页打开新文件而不是用新窗口打开,将以下配置改为false(默认为true) 
- 627D Preorder Test
			传送门 题目大意 给出一棵无根树,每个节点有一个权值,现在要让dfs序的前k个结点的最小值最大,求出这个值.分析 首先可以对这个值v进行二分然后01分数规划现在问题转化为求出一个dfs序,使得dfs序 ... 
- Flask框架 之 学生管理分析
			先看模板吧. index.html <body> <h1>学生列表</h1> <table border="1"> <thea ... 
- html5操作类名API——classlist
			tagNode.classList.add('123'); // 添加类 tagNode.classList.remove('bbb'); // 删除类 tagNode.classList.toggl ... 
- C#将DataTable数据导出到EXCEL的两种方法
			1.在非服务器控件的页面导出数据,需要借助一张temp空页面post回后台的数据. 前台:window.location.href = "../Temp.aspx"; 后台: tr ... 
- CodeForces 489E Hiking (二分+DP)
			题意: 一个人在起点0,有n个休息点,每个点有两个数值,分别表示距离起点的距离xi,以及所获得的愉悦值bi,这个人打算每天走L距离,但实际情况不允许他这么做.定义总体失望值val = sum(sqrt ... 
- 验证码-WebVcode
			验证码的实现 <img src="../Common/WebVcode.aspx" title="看不清?点此更换" alt="看不清?点此更换 ... 
- Python中多使用迭代器
			英文原文出处:Use More Iterators 本文介绍将代码转换为使用迭代器的原因和实用技巧. 我最喜欢的Python语言的特色之一是生成器,它们是非常有用的,然而当阅读开源代码时,我很少遇到它 ... 
