zoukankan      html  css  js  c++  java
  • 51Nod 1299 监狱逃离

    这其实是一道树形DP的神仙题。

    然后开始推推推,1 hour later样例都过不了

    然后仔细一看题目,貌似像一个最小割模型,然后5min想了想建图:

    1. 首先拆点,将每个点拆成进和出两个,然后连边,边权即为(1)(表示割掉这条边的代价)
    2. 然后设超级源(S),让(S)向所有犯人的出点(因为犯人的点无法割去)连边,边权为(infty),然后对于所有的出口(叶子节点),都向(T)连边,边权为(infty)
    3. 最后根据题目给出的关系建边,然后因为这些边不可以被割掉,因此边权为(infty)

    然后据说Dinic的最劣复杂度是(O(n^2m))的,所以直接没有畏惧地交了

    然后A了?!第一次看到51Nod的题数据这么水(然后莫名复习了一波网络流

    当然正解是树形DP,当然可以看陈潇然dalao的博客

    DinicCODE

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    using namespace std;
    const int N=100005,INF=1e9;
    struct edge
    {
    	int to,next,c;
    }e[N<<4];
    int head[N<<1],n,cnt=-1,m,x,y,dep[N<<1],q[N<<1],s,t,l[N<<1];
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch; while (!isdigit(ch=tc()));
    	while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
    }
    inline void double_add(int x,int y,int z)
    {
    	e[++cnt].to=y; e[cnt].next=head[x]; e[cnt].c=z; head[x]=cnt; ++l[x];
    	e[++cnt].to=x; e[cnt].next=head[y]; e[cnt].c=0; head[y]=cnt; ++l[y];
    }
    inline int min(int a,int b)
    {
    	return a<b?a:b;
    }
    inline bool BFS(void)
    {
    	memset(dep,0,sizeof(dep));
    	int H=0,T=1; dep[s]=1; q[1]=s;
    	while (H<T)
    	{
    		int now=q[++H];
    		for (register int i=head[now];~i;i=e[i].next)
    		if (e[i].c&&!dep[e[i].to])
    		{
    			dep[e[i].to]=dep[now]+1;
    			q[++T]=e[i].to;
    		}
    	}
    	return dep[t];
    }
    inline int DFS(int now,int dist)
    {
    	if (now==t) return dist; int res=0;
    	for (register int i=head[now];~i&&dist;i=e[i].next)
    	if (e[i].c&&dep[e[i].to]==dep[now]+1)
    	{
    		int dis=DFS(e[i].to,min(dist,e[i].c));
    		dist-=dis; res+=dis;
    		e[i].c-=dis; e[i^1].c+=dis;
    	}
    	if (!res) dep[now]=0;
    	return res;
    }
    inline int Dinic(void)
    {
    	int tot=0;
    	while (BFS()) tot+=DFS(s,INF);
    	return tot>=INF?-1:tot;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i; read(n); ++n; read(m); s=0; t=(n<<1)+1;
    	memset(head,-1,sizeof(head));
    	for (i=1;i<n;++i)
    	read(x),read(y),++x,++y,double_add(x+n,y,INF),double_add(y+n,x,INF);
    	for (i=1;i<=m;++i)
    	read(x),++x,double_add(s,x+n,INF);
    	for (i=1;i<=n;++i)
    	{
    		if (l[i]==1) double_add(i+n,t,INF);
    		double_add(i,i+n,1);
    	}
    	return printf("%d",Dinic()),0;
    }
    
  • 相关阅读:
    彻底禁用resource manager
    NYOJ_94 cigarettes 递归VS迭代
    itunes connect上传截图提示无法加载文件问题
    hdu 1165 Eddy&#39;s research II(数学题,递推)
    USACO holstein 超时代码
    金蝶KIS标准版与金蝶K3的差别
    OC第三天(内存管理)
    HDU 1059 Dividing(多重背包)
    说说參数传递(泛型托付)
    Json数组操作小记 及 JSON对象和字符串之间的相互转换
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9356428.html
Copyright © 2011-2022 走看看