bzoj 1312: Hard Life 01分数规划+网络流

本文介绍了一种解决特定冲突最大化问题的算法实现。通过构建图论模型并运用Dinic算法求解最大流问题,以此来确定能形成最高冲突度的工作小组成员组合。文章详细展示了如何将人际关系间的矛盾转化为图中的边权值,并最终找到最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

Description
在一家公司中,人事部经理与业务部经理不和。一次,总经理要求人事部从公司的职员中挑选出一些来帮助业务部经理完成一项任务。人事部经理发现,在公司的所有职员中,有一些人相处得很不好。如果把他们同时放在一个工作小组中,他们将会给主管带来不小的麻烦。人事部经理还知道,在一个工作小组中,主管人员的麻烦程度可以认为是(带来麻烦的人的对数/总人数) 。于是,人事部经理决定选取这样的一些人,使得业务部经理的麻烦度最大。你的任务是帮助人事部经理达到他的目的。 在这样的一个公司中,保证公司的人数小于100 人,带来麻烦的员工不会多于1000 对。
Input
第一行给出N,M代表共有N个人,M对人之间有怨念 下面M行,每行两个数,代表这两个人有怨念
Output
输出最多能找出多少个人,人数>=1

题解:

我不想写这道题的题解
1055088-20170314212946432-1897666504.png
1055088-20170314212952213-2135888734.png
1055088-20170314213002557-1228054543.png
1055088-20170314213010135-431409876.png
1055088-20170314213013823-1223149232.png
1055088-20170314213017885-1645077440.png
1055088-20170314213026276-425114222.png
Sky_miner是我的号hzoi_admin是我提交次数不够了借用的号.
求不D

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
typedef int ll;
inline void read(int &x){
    x=0;char ch;bool flag = false;
    while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 80048;
const int maxm = 100005;
const int maxnode = (maxn+maxm)<<1;
struct Edge{
    int to,next;
    long double cap;
}G[maxnode];
int head[maxnode],cnt=1;
void add(int u,int v,long double c){
    G[++cnt].to = v;
    G[cnt].next = head[u];
    head[u] = cnt;
    G[cnt].cap = c;
}
inline void insert(int u,int v,long double c){
    add(u,v,c);add(v,u,0);
}
inline void clear(){
    memset(head,-1,sizeof head);
    cnt = 1;
}
#define v G[i].to
int dis[maxnode];
int S,T;
inline bool bfs(){
    memset(dis,-1,sizeof dis);
    queue<int>q;q.push(S);
    dis[S] = 0;
    while(!q.empty()){
        int u = q.front();q.pop();
        for(int i = head[u];i != -1;i=G[i].next){
            if(dis[v] == -1 && G[i].cap > 1e-8){
                dis[v] = dis[u] + 1;
                q.push(v);
            }
        }
    }return dis[T] != -1;
}
long double dfs(int u,long double f){
    if(u == T || fabs(f) < 1e-8) return f;
    long double ret = 0;
    for(int i = head[u];i != -1;i=G[i].next){
        if(dis[v] == dis[u] + 1 && G[i].cap > 1e-8 ){
            long double x = dfs(v,min(G[i].cap,f));
            ret += x;f -= x;
            G[i].cap -= x;
            G[i^1].cap += x;
            if(fabs(f) < 1e-8) break;
        }
    }return ret;
}
#undef v
inline long double dinic(){
    long double ret = 0;
    while(bfs()) ret += dfs(S,1e9);
    return ret;
}
struct Node{
    int u,v;
}e[maxm];
int n,m;
bool check(double ans){
    memset(head,-1,sizeof(head));cnt=1;
    double sum=m;S=0;T=n+m+1;
    for(int i=1;i<=n;++i){
        insert(S,i,ans);
    }
    for(int i=1;i<=m;++i){
        insert(n+i,T,1);
        insert(e[i].u,n+i,1e9);
        insert(e[i].v,n+i,1e9);
    }
    return sum>dinic();
}
int dfn[maxn];
int ans;
void DFS(int x){
    if(1<=x&&x<=n)ans--;
    dfn[x]=1;
    for(int pt=head[x];pt!=-1;pt=G[pt].next){
        if(G[pt].cap>1e-3&&!dfn[G[pt].to])DFS(G[pt].to);
    }
}
int main(){
    read(n);read(m);
    if(m == 0) return puts("1");
    for(int i=1;i<=m;++i){
        read(e[i].u);read(e[i].v);
    }
    long double l = .0,r = 1e4;
    while(l + 1e-5 < r){
        long double mid = (l+r)/2.0;
        if(check(mid)) l = mid;
        else r = mid;
    }ans = n;
    DFS(S);
    printf("%d\n",max(ans,1));
    getchar();getchar();
    return 0;
}

转载于:https://www.cnblogs.com/Skyminer/p/6550838.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值