[2017百度之星程序設計大賽 - 複賽]F - hdu6149

因爲是三元組<x,y,z>
暴力枚舉處於x位置的高谷,然後建網絡流的圖,每次跑dinic取最大流。
枚舉位置時直接dfs,上界是高谷總數的一半。
可以證明答案一定在dfs出的結果內。

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
int T,n,m,k,kd;
int hi[100],tot,ans;
int map[100][100];
int le[100];
bool in[100];
bool ff[100];
int s,t;
struct edge{
    int ro, flow, v, nxt;
}e[2500];
int num;
int cur[100];
int vis[100];
int dis[100];
int head[100];
inline void add_e(int ro,int u,int v)
{
    e[num].ro=ro,e[num].v=v,e[num].flow=0,e[num].nxt=head[u],head[u]=num,num++;
    e[num].ro=0,e[num].v=u,e[num].flow=0,e[num].nxt=head[v],head[v]=num,num++;
}
inline bool bfs(int s,int t)  
{  
    int i;  
    memset(vis,0,sizeof(vis));  
    queue<int> q;  
    dis[s]=0;vis[s]=1;  
    q.push(s);  
    while (!q.empty())  
    {  
        int x=q.front();  
        q.pop();  
        for (i=head[x];i;i=e[i].nxt)  
        {  
            if (!vis[e[i].v]&&e[i].ro>e[i].flow)  
            {  
                q.push(e[i].v);  
                vis[e[i].v]=1;  
                dis[e[i].v]=dis[x]+1;  
            }  
        }  
    }  
    return vis[t];  
}  
inline int dfs(int x,int a)  
{  
    if (x==t||a==0) return a;  
    int flow=0,f;  
    for (int& i=cur[x];i;i=e[i].nxt)  
    {  
        if (dis[x]+1==dis[e[i].v]&&((f=dfs(e[i].v,min(a,e[i].ro-e[i].flow)))>0))  
        { 
            e[i].flow+=f;  
            e[i^1].flow-=f;  
            flow+=f;  
            a-=f;  
            if (a==0) break;  
        }  
    }  
    return flow;  
}  
int dinic(int S,int T)
{
    int fwf=0;
    while (bfs(S,T))
    {
        for (int i=0;i<=n+n+1;i++) cur[i]=head[i]; 
        fwf+=dfs(s,0x3f3f3f);
    }
    return fwf;
}
inline int make()
{
    int i=0,j=0;
    num=2;
    s=0,t=n+n+1;
    memset(head,0,sizeof(head));
    for (i=1;i<=kd;i++) add_e(1,s,le[i]);
    for (i=1;i<=n;i++) if (!in[i]) add_e(1,i,i+n);
    for (i=1;i<=n;i++) if (in[i]&&!ff[i]) add_e(1,i,t);
    for (i=1;i<=kd;i++)
    {
        for (j=1;j<=n;j++)
        {
            if (map[le[i]][j]&&!in[j])
            add_e(1,le[i],j);
        }
    }
    for (i=1;i<=n;i++)
    {
        if (!in[i])
        {
            for (j=1;j<=n;j++)
            {
                if (in[j]&&!ff[j]&&map[i][j])
                add_e(1,i+n,j);
            }
        }
    }
    return dinic(s,t);
}
void dfs1(int now,int tot)
{
    if (k-now+tot+1<kd) return ;
    if (tot==kd) {ans=max(make(),ans);return ;}
    if (now>k) return ;
    le[++tot]=hi[now];ff[hi[now]]=1;
    dfs1(now+1,tot);--tot;ff[hi[now]]=0;
    dfs1(now+1,tot);
}
int main()
{
    register int i,j,l;
    scanf("%d",&T);
    for (l=1;l<=T;l++)
    {
        memset(in,0,sizeof(in));
        memset(hi,0,sizeof(hi));
        memset(map,0,sizeof(map));
        scanf("%d %d %d",&n,&m,&k);
        kd=k/2;
        int x,y;tot=ans=0;
        for (i=1;i<=m;i++)
        {
            scanf("%d %d",&x,&y);
            map[x][y]=map[y][x]=1;
        }
        for (i=1;i<=k;i++) scanf("%d",&hi[++tot]),in[hi[tot]]=1;;
        dfs1(1,0);
        printf("%d\n",ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章