• bzoj1565: [NOI2009]植物大战僵尸 最大权闭合子图,tarjan


    bzoj1565: [NOI2009]植物大战僵尸

    链接

    https://www.lydsy.com/JudgeOnline/problem.php?id=1565

    思路

    很容易的想到最大权闭合子图
    但这个图是有环的
    有环的地方当然是都过不去的地方
    显然他所保护的地方也是过不去的
    他保护的地方的保护的地方也是过不去的
    等等
    还有这个这一行的[1,i]也是过不去的
    tarjan之后递归判一下就行了

    错误

    好菜欧,调试了半天
    其实我一开始以为环上就有了他所保护的地方
    改了之后又没想到他保护的地方的保护的地方也是不可以过去的
    好菜欧

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e6+7,M=107,inf=0x3f3f3f3f;
    int read() {
    	int x=0,f=1;char s=getchar();
    	for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    	for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    	return x*f;
    }
    int n,m,S,T,Score[M][M],id[M][M];
    vector<pair<int,int> > dsr[M][M];
    bool mmp[M][M];
    pair<int,int> kkk[M*M];
    struct node {
    	int u,v,nxt,cap;
    }e[N];
    int head[N],tot=1;
    void add_edge(int u,int v,int cap) {
    	e[++tot].u=u;
    	e[tot].v=v;
    	e[tot].cap=cap;
    	e[tot].nxt=head[u];
    	head[u]=tot;
    }
    void add(int u,int v,int cap) {
    	add_edge(u,v,cap);
    	add_edge(v,u,0);
    }
    int dis[N];
    queue<int> q;
    bool bfs() {
    	memset(dis,-1,sizeof(dis));
    	q.push(S);
    	dis[S]=0;
    	while(!q.empty()) {
    		int u=q.front();
    		q.pop();
    		for(int i=head[u];i;i=e[i].nxt) {
    			int v=e[i].v;
    			if(dis[v]==-1&&e[i].cap) {
    				dis[v]=dis[u]+1;
    				q.push(v);
    			}
    		}
    	}
    	return dis[T]!=-1;
    }
    int dfs(int u,int f) {
    	if(u==T) return f;
    	int rest=f;
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(dis[v]==dis[u]+1&&e[i].cap&&rest) {
    			int t=dfs(v,min(e[i].cap,rest));
    			if(!t) dis[v]=0;
    			e[i].cap-=t;
    			e[i^1].cap+=t;
    			rest-=t;
    		}
    	}
    	return f-rest;
    }
    int dinic() {
    	int ans=0;
    	while(bfs())
    		ans+=dfs(S,inf);
    	return ans;
    }
    int dfn[N],low[N],stak[N],top,cnt,vis[N],belong[N];
    vector<int> BE[N];
    void tarjan(int u) {
    	dfn[u]=low[u]=++cnt;
    	vis[u]=1;
    	stak[++top]=u;
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(!e[i].cap) continue;
    		if(!dfn[v]) {
    			tarjan(v);
    			low[u]=min(low[u],low[v]);
    		} else if(vis[v]) {
    			low[u]=min(low[u],dfn[v]);
    		}
    	}
    	if(low[u]==dfn[u]) {
    		belong[0]++;
    		while(stak[top]!=u) {
    			vis[stak[top]]=0;
    			belong[stak[top]]=belong[0];
    			BE[belong[0]].push_back(stak[top]);
    			top--;
    		} top--;
    		vis[u]=0;
    		BE[belong[0]].push_back(u);
    		belong[u]=belong[0];
    	}
    }
    void AC(int u) {
    	if(mmp[kkk[u].first][kkk[u].second]) return;
    	for(int k=1;k<=kkk[u].second;++k) mmp[kkk[u].first][k]=1;
    	mmp[kkk[u].first][kkk[u].second]=1;
    	for(vector<pair<int,int> >::iterator it=dsr[kkk[u].first][kkk[u].second].begin();it!=dsr[kkk[u].first][kkk[u].second].end();++it)
    	// for(auto it : dsr[kkk[u].first][kkk[u].second])
    		AC(id[it->first][it->second]);
    }
    int main() {
    	n=read(),m=read();
    	for(int i=1,js=0;i<=n;++i) { for(int j=1;j<=m;++j) {
    		id[i][j]=++js;
    		kkk[js]=make_pair(i,j);
    	}}
    	for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) {
    		Score[i][j]=read();
    		int gs=read();
    		for(int k=1;k<=gs;++k) {
    			int x=read()+1,y=read()+1;
    			dsr[i][j].push_back(make_pair(x,y));
    		}
    		if(j>1)
    		dsr[i][j].push_back(make_pair(i,j-1));
    	}}
    	S=n*m+1,T=n*m+2;
    	for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) {
    		for(vector<pair<int,int> >::iterator it=dsr[i][j].begin();it!=dsr[i][j].end();++it) {
    			add(id[i][j],id[it->first][it->second],inf);
    		}
    	}}
    	for(int i=1;i<=n*m;++i)
    		if(!dfn[i])
    			tarjan(i);
    	for(int i=1;i<=tot;i++) {
    		if(belong[e[i].u]==belong[e[i].v]) {
    			AC(e[i].u);
    		}
    	}
    	memset(head,0,sizeof(head));
    	memset(e,0,sizeof(e));
    	tot=1;
    	for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) {
    		if(mmp[i][j]==1) continue;
    		if(j!=m&&mmp[i][j+1]!=1) add(id[i][j],id[i][j+1],inf);
    		// for(auto it : dsr[i][j]) {
    		for(vector<pair<int,int> >::iterator it=dsr[i][j].begin();it!=dsr[i][j].end();++it) {
    			if(mmp[it->first][it->second]!=1)
    			add(id[it->first][it->second],id[i][j],inf);
    		}
    	}}
    	int sum=0;
    	for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) {
    		if(Score[i][j]>0&&!mmp[i][j]) sum+=Score[i][j];
    		if(mmp[i][j]==1) continue;
    		if(Score[i][j]>0) add(S,id[i][j],Score[i][j]);
    		else add(id[i][j],T,-Score[i][j]);
    	}}
    	int ans=sum-dinic();
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    针式PKM软件进入华军分类下载月排名前6名
    读取xml
    一个简单的记事本程序
    python输出重定向
    重看ATL布幔之下的秘密
    nginx学习(二)动态加载各模块
    ngx_queue的理解
    nginx学习(三)IOCP的使用
    nginx学习(一)内存
    使用python实现一个通用协议测试工具
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10506199.html
Copyright © 2020-2023  润新知