問題の説明
ジョンは、個人所有の中規模企業で最高経営責任者(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;
}