ハードライフ(POJ-3155)(図式最大重量を閉じ)

問題の説明

ジョンは、個人所有の中規模企業で最高経営責任者(CEO)です。会社の所有者は、彼の息子スコットの会社でマネージャーを作ることにしました。ジョンは彼が彼の新しいマネージャーの位置にもない場合は、所有者が最終的にスコットにCEOの地位を与えることを恐れているので、彼は慎重に、彼は会社で管理しようとしているチームを選択することにより、可能な限りハードとしてスコットの生活を作ることにしました。

ジョンは彼の人々のペアが同じチームで十分に機能しないかを知っています。ジョンは導入された  硬さの要因  チームのを-それはチームの人の合計数で割った、同じチームに十分に機能しないこのチームからの人々のペアの数です。大きい方が難しく、硬度因子で管理するには、このチームです。ジョンは管理し、それスコットのチームにするために最も困難です会社に人々のグループを見つけたいです。、彼を助けてください。

5対が同じチームに難働くそれらの4のうち最も困難なチームが人1、2、4から構成画像、及び5での例では、このように硬さ係数は5/4に等しいです。我々はチームに一人の番号3を追加した場合、硬度率は6/5に減少します。

 

入力

入力ファイルの最初の行は、2つの整数の番号が含まれ、nおよびm(1≤N≤100、0≤M≤1000)。ここで、nは(人が1からnまでの番号が付けられている)企業における人の合計数であり、mは同じチームで十分に機能しない人々のペアの数です。次のm行は、2つの整数番号を有するものペアがAIとBI(1≤、BI aiを≤N、aiを≠BI)の行に記載されています。ペアの人の順番は任意であり、何のペアが2回表示されません。

出力

出力ファイルへの書き込み(≤K≤nは1)の整数番号k - 最も難しいチームの人数、昇順でこのチームから人々をリストするk個の行が続きます。同じ硬さ係数を持つ複数のチームがある場合は、いずれかを書きます。

サンプル入力

サンプル入力#1
5 6
1 5
5 4
4 2
2 5
1 2
3 1

サンプル入力#2
4 0

サンプル出力

サンプル出力#1
4
1
2
4
5

サンプル出力#2
1
1

質問の意味:複数のデータセットを、それぞれ与えられたN、M二つの数字、N個の個別の会社を表すが、m個の競合関係が存在しており、今の会社は、解雇することを決定し、これらの競合を含む紛争の最高速度を、切断します=カット出力に競合/数がある人の数、及び人の合計数

アイデア:

単にこれらの点/最大点間のエッジの数、すなわち、最大濃度サブグラフを求めるように、n個のドット及びM縁与えられ、入れていくつかの時点で取得

この問題は、最大の密度のサブタイトルテンプレートマップ、最大重量+クローズドグラフモデルの使用の半分は解決することができ、具体的なアイデアであると言うことができます。こちらをクリック

ソースプログラム

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
LL quickPow(LL a,LL b){ LL ans=1; while(b){if(b&1)ans*=a; a*=a; b>>=1;} return ans; }
LL multMod(LL a,LL b,LL mod){ a%=mod; b%=mod; LL ans=0; while(b){if(b&1)ans=(ans+a)%mod; a=(a<<=1)%mod; b>>=1; } return ans%mod;}
LL quickMultPowMod(LL a, LL b,LL mod){ LL ans=1,k=a; while(b){if((b&1))ans=multMod(ans,k,mod)%mod; k=multMod(k,k,mod)%mod; b>>=1;} return ans%mod;}
LL quickPowMod(LL a,LL b,LL mod){ LL ans=1; while(b){if(b&1)ans=(a*ans)%mod; a=(a*a)%mod; b>>=1; } return ans; }
LL getInv(LL a,LL mod){ return quickPowMod(a,mod-2,mod); }
LL GCD(LL x,LL y){ return !y?x:GCD(y,x%y); }
LL LCM(LL x,LL y){ return x/GCD(x,y)*y; }
const double EPS = 1E-6;
const int MOD = 1000000000+7;
const int N = 1500+5;
const int dx[] = {0,0,-1,1,1,-1,1,1};
const int dy[] = {1,-1,0,0,-1,1,-1,1};
using namespace std;
 
struct Edge {
    int to, next;
    double cap;
} edge[80 * N]; 
Pair pastEdge[N];//原图边集
int head[N],tot;
int n,m,S,T;
int ans;//层数
int level[N];//记录层次
int gap[N];//记录每组层次标号有几个
int numNode;//最大密度子图中点的个数
bool vis[N];//标记最大密度子图中的点
void addedge(int x, int y, double cap) {
    edge[tot].to = y;
    edge[tot].cap = cap;
    edge[tot].next = head[x];
    head[x] = tot++;
 
    edge[tot].to = x;
    edge[tot].cap = 0;
    edge[tot].next = head[y];
    head[y] = tot++;
}
void makeMap(double g) {
    memset(head,-1,sizeof(head));  
    tot=0;
 
    for(int i=1;i<=n;i++)//原图中的点到汇点 
        addedge(i,T,g); 
    for(int i=0;i<m;i++) {  
        //源点到原图中的每条边
        addedge(S,n+i+1,1.0);
        //原图中的每条边到之间建边
        addedge(n+i+1,pastEdge[i].first,INF);  
        addedge(n+i+1,pastEdge[i].second,INF);  
    }  
}
double dfs(int x, double minflow) {
    if (x == T)
        return minflow;
 
    double flow = 0.0;
    for (int i = head[x]; i != -1; i = edge[i].next) {
        int y = edge[i].to;
        if (edge[i].cap > 0) {
            if (level[y] + 1 == level[x]) {
                double newFlow =
                    edge[i].cap > minflow - flow ? minflow - flow : edge[i].cap;
                newFlow = dfs(y, newFlow);
 
                flow += newFlow;
                edge[i].cap -= newFlow;
                edge[i ^ 1].cap += newFlow;
 
                if (minflow - flow <= EPS)
                    return flow;
                if (level[S] >= ans)
                    return flow;
            }
        }
    }
 
    if (--gap[level[x]] == 0)
        level[S] = ans;
    level[x]++;
    gap[level[x]]++;
    return flow;
}
double ISAP() {
    double maxflow=0.0;    
    memset(gap,0,sizeof(gap));    
    memset(level,0,sizeof(level));  
    gap[0]=ans;    
 
    while(level[S]<ans)
        maxflow+=dfs(S,INF);
 
    return 1.0*m-maxflow;     
}
void findNode(int x) {//寻找残量网络中可到达的点
    vis[x] = true;
    if (x >= 1 && x <= n)
        numNode++;
    for (int i = head[x]; i != -1; i = edge[i].next) {
        int y = edge[i].to;
        if (vis[y] == false && edge[i].cap > 0)
            findNode(y);
    }
}
int main() {
    while (scanf("%d%d", &n, &m) != -1) {
        if (m == 0) {
            printf("1\n1\n");
            continue;
        }
 
        S=0,T=n+m+1;
        ans=T+1;  
        
        for(int i=0;i<m;i++)  
            scanf("%d%d",&pastEdge[i].first,&pastEdge[i].second);
 
        double left = 0, right = m;
        while (right - left >= 1.0 / (n*n)) { //论文给出了证明,不同解之间误差的精度不超过1/(n*n)
            double mid = (left + right) / 2;
            makeMap(mid); //根据mid值重新建图
 
            if (ISAP() < EPS) //如果小于0,g值太大,调整上界
                right = mid;
            else
                left = mid;
        }
        // printf("%lf",left);//最大密度
 
        makeMap(left); //根据最大密度建图
        ISAP();        //求最大权闭合图
 
        //寻找最大密度子图中的点
        numNode = 0;
        memset(vis, false, sizeof(vis));
        findNode(S);
        printf("%d\n", numNode);
        for (int i = 1; i <= n; i++)
            if (vis[i])
                printf("%d ", i);
        printf("\n");
    }  
    return 0;  
} 

 

リリース1871元の記事 ウォンの賞賛702 ビュー194万+

おすすめ

転載: blog.csdn.net/u011815404/article/details/102683853