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\n",ans);
	return 0;
}
posted @ 2019-03-10 17:59  ComplexPug  阅读(433)  评论(0编辑  收藏  举报