최단 경로 문제의 흐름 범위

최근 간 네트워크는 상단에 작은 흐름
사실, 난 그냥 물 블로그 제목을 원하는 싶지 않아
완료되기 전에 블로그 넌센스
으로 \ (루오 \ 번지는 \) 24 개 질문 중 하나 고전적인 네트워크 종양은 물론의 블로그 쓰기
전송


결국 제목에 무슨 말을?

존재하는 DAG.도 임의의 경로를 선택할 이제 각 경로가 선택되어, 경로에 포함 +1 점의 수, 모든 지점이 포함되어있는 점 번만 포함되도록. 선택된 경로의 수는 커버리지 경로이다. 최소 경로 범위는 경로의 최소 수있다.

다음은 간단한 밤나무

1 덮는 최단 경로가 분명

레드 핫 패스되고

당신이주는 경우에 우리가 수행하는 방법의 매우 복잡한 견해는 무엇입니까?
이 경로는 가장 큰 것은 N-1 음주 운전의 쌍 커버? (폭력 등의 선출 나무 같은 것들, 그것은 N-1 가장자리가)
우리가 경로의 범위가 작아 고려
> B와 b - -이 있지만 우리가 선출하는 경우> C면 다음, 그들은 하나 개의 경로로 결합 할 수 있도록 응답 -1
물론이 기간 B에 주목있을 경우 -> D면은 후 -> 단 B b로부터 -> C 및 B - 선택된> d는 병합
후 최소 경로 범위가 통합 측을 계속하는 것입니다, 그것은 더 이상까지 합병에 통합되었습니다

분명히 우리는이 일을하고 네트워크 흐름을 문의해야(그렇지 않으면 네트워크가 종양 24 문제라는 방법)
네트워크 흐름은 이분 그래프 매칭을 생각 맞물 리도록 할 수 있습니다
우리는이 작업 점을 분할 한 기대하는

분할 소수점 연산은 게이샤입니다

도트가 두 지점 및 아웃 포인트로 분할 될 상기 관통 점만이 침투뿐만 아니라도 지적하지 않는다.
가장자리와 종점 지점에도 동안은, 측면의 관점에서 그 시점을 의미

포인트 및 아웃점 종료 후 발견 된 그래프 그

이 마법의 작동, 우리는 한면을 병합 할 때마다, 경기를 선출한다. 우리는 많은면을 병합 할, 이분 그래프의 최대 매칭되는 많은 일치로 선출

여기에 있습니다 헝가리이 좋은 물건을 (또한 부수적으로 경로를 기록)를 사용할 수 있습니다 이분 그래프 최대 매칭 알고리즘을 추구하지만, 네트워크 네트워크 종양 세계 사회가 , 우리는 네트워크 흐름 밖으로의 사용을 고려한다.

도 위의 내장 가야 (가 스트리밍 네트워크를 얻을 수와 동일), 다음 단계는 암의 경로를 기록하는 것입니다

실수 + N,이 예비 처리 될 수있다 YS (MAP) 어레이, YS의 포인트 개수도 시점의 구성되어 고려 [I]는 i 포인트 실수 (대 즉, I> N 때 YS [이고 I =)에서

만약 잔량 (즉 DIS) 0 한쪽 계정으로 네트워크 흐름의 원리를 복용 후, 우리는 이것을 선택한 매치, 즉 동일한 경로 가장자리에의 부착 점을 말할 수있다. 있도록 출력 경로 DFS를 사용하여 달성 될 수있다. DFS는 그 뒷면을 고려할 때합니다.

직접 연결된 코드의 쌍

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=214748364;
typedef long long ll;
inline int read()
{
    char ch=getchar();
    int x=0;bool f=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return f?-x:x;
}
int n,m,head[409],cnt=1,ans,s,t;
struct E{
    int to,nxt,dis;
}ed[12009];
int dep[409],cur[409];
queue <int> q;
int ys[409];
bool vis[159];
inline void add(int fr,int to,int dis)
{
    cnt++;
    ed[cnt].to=to;
    ed[cnt].dis=dis;
    ed[cnt].nxt=head[fr];
    head[fr]=cnt;
}
inline bool bfs()
{
    for(int i=1;i<=2*n+2;i++)
     dep[i]=0;
    for(int i=1;i<=2*n+2;i++)
     cur[i]=head[i];
    dep[s]=1; 
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int e=head[u];e;e=ed[e].nxt)
        {
            int v=ed[e].to;
            if(ed[e].dis&&!dep[v])
            {
                dep[v]=dep[u]+1;
                q.push(v);
            }
        }
    }
    return dep[t];
}
int dfs(int now,int in)
{
    if(now==t)return in;
    int out=0;
    for(int e=cur[now];e;e=ed[e].nxt)
    {
        cur[now]=e;
        int v=ed[e].to;
        if(ed[e].dis&&dep[v]==dep[now]+1)
        {
        int ret=dfs(v,min(in,ed[e].dis));
            ed[e].dis-=ret;
            ed[e^1].dis+=ret;
            in-=ret;
            out+=ret;
            if(!in) return out;
        }
    }
    return out;
}
inline void dinic()
{
    int ret;
    while(bfs())
    {
         ret=0;
         while(ret=dfs(s,20000000))ans+=ret;
    }
}
//上面全是网络流
void lj(int u)//路径不是辣鸡 !!!
{
     printf("%d ",u);
    vis[u]=1;//vis记录是否已经输出
    for(int e=head[u];e;e=ed[e].nxt)
    {
        int v=ed[e].to;
        if(v==s||v==t)continue;//这里注意不考虑自己加的超源,超汇
        if(!ed[e].dis&&!vis[ys[v]])
          lj(ys[v]); 
    }
}
int main()
{
    n=read();m=read();s=n*2+1;t=n*2+2;
    for(int i=1;i<=m;i++)
    {
        int fr=read(),to=read();
        add(fr,to+n,1);add(to+n,fr,0);
    }
    for(int i=1;i<=n;i++)
     add(s,i,1),add(i,s,0);
    for(int i=n+1;i<=2*n;i++)
     add(i,t,1),add(t,i,0);
    for(int i=1;i<=n;i++)
     ys[i]=i;
    for(int i=n+1;i<=2*n;i++)
     ys[i]=i-n;
    ys[s]=s;ys[t]=t;
    dinic();
    ans=n-ans;
    for(int i=1;i<=n;i++)//这里就不从超源开始考虑了qwq
    {
        if(!vis[i])
        {
            lj(i);
        printf("\n");
        }
    }
    printf("%d",ans);
}

추천

출처www.cnblogs.com/lcez56jsy/p/11406174.html