説明フェイス質問
極東では、神秘的な国が主張し、そこにある\(Y \)家族を。彼らは、水、ドラゴンキング奉神上の世代のために住んでいました。すべての主要な祭典、\(Y- \)家族が水の上に壮大な祭りを開催します。私たちはできる(Y \)\構成道路や河川ネットワークの分岐点として、川で家族の住居を。各チャネルは、二つのフォークに接続されており、水がチャネル中に一定方向に流れます。明らかに、何の循環(図循環における一例を説明する)は、水性系は存在しません。
理由により多数に、\(Y- \)家族の祭りは、複数のフォークで同時に開催されます。ドラゴンキングの尊重のうち、礼拝は、これらの選択肢は非常に慎重でなければなりません置きます。むしろ、\(Y- \)部族は、水が別の儀式犠牲ポイントに一点から流れることができるならば、その儀式はその神聖な意義を失うことになると信じています。総主教は、礼拝のように多くの場所を選択し、儀式の神聖さを維持するための基礎を期待しています。
入力形式
- 最初の行は、スペースで区切られた2つの整数含有(2 ^ N 10、M≤10を≤3 ^ \)\を、から川フォークの数、フォークを表す\(1 \)する(N \)\数。
- 次\(M \)行、スペースで区切られた2つの整数を含む各行\(U、V \)は、接続フォーク説明\(U \)とフォーク\(V \)河川水の流れ方向を以来、\(uが\)する\(V \) 。
出力フォーマット
- 最初の行は、整数含ま\(K \)を、犠牲の選択された点に番号を示しています。
問題の解決策
- 最小の架橋被覆(最大逆鎖)
質問のいくつかの明確な思考....- まず、参照(N \の当量10 ^ 2 \ \) について知って\(O(N ^ 3) \) アルゴリズム、またはネットワークフロー。その後、下記のタイトルを制限するために見て、別のストリームから2つの点を犠牲に必要ですが、一点だけのための1つの鎖は、二本の鎖が考える可能性がある場合、相互にアクセスできないことを意味することはできません。そこで、図の鎖の最小の数でこれをカバーするために必要。最低限の連携をカバーするために探しています。
- 具体的には:最初と\(フロイド\)も点をエッジ点に推移閉包、2点の点(IN点、OUT点)に、各スプリットを取得し、配信ポイントに応じて閉鎖を置くことができ両方の能力ながら、全ての点は、プラス側に接続されている\(1 \) 。最大フローを実行し、\(MaxFlowを\) 、答えは\(N-maxflow \)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN=2e2+5;
const int MAXM=2e5+5;
const int inf=1e9;
int a[MAXN][MAXN];
int n,m,S,T;
int edge=1,head[MAXN],nex[MAXM],tail[MAXM],r[MAXM];
int d[MAXN],cur[MAXN];
queue<int> q;
void add(int u,int v,int R){
edge++,nex[edge]=head[u],head[u]=edge,tail[edge]=v,r[edge]=R;
}
void ins(int u,int v,int R){
add(u,v,R); add(v,u,0);
}
bool bfs(){
for (int i=1;i<=T;i++) d[i]=inf;
d[S]=0; q.push(S);
while (!q.empty()){
int u=q.front(); q.pop();
for (int e=head[u];e;e=nex[e]){
int v=tail[e];
if (d[v]==inf&&r[e]>0){
d[v]=d[u]+1;
q.push(v);
}
}
}
return d[T]<inf;
}
int dfs(int u,int b){
if (u==T) return b;
int ans=0;
for (int& e=cur[u];e;e=nex[e]){
int v=tail[e];
if (d[v]==d[u]+1&&r[e]>0){
int res=dfs(v,min(b,r[e]));
r[e]-=res; r[e^1]+=res;
b-=res; ans+=res;
}
if (!b) break;
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++) a[i][j]=1e9;
}
for (int i=1;i<=m;i++){
int u,v; scanf("%d%d",&u,&v);
a[u][v]=1;
}
for (int k=1;k<=n;k++){
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
if (a[i][j]>a[i][k]+a[k][j]){
a[i][j]=a[i][k]+a[k][j];
}
}
}
}
S=2*n+2;T=S+1;
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
if (a[i][j]<inf&&i!=j) ins(2*i+1,2*j,1);
}
ins(S,2*i+1,1); ins(2*i,T,1);
// ins(2*i,2*i+1,1);
}
int flow=0;
while (bfs()){
for (int i=1;i<=T;i++) cur[i]=head[i];
flow+=dfs(S,inf);
}
printf("%d\n",n-flow);
return 0;
}