• 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;
    }
    
  • 相关阅读:
    CSUFT 1002 Robot Navigation
    CSUFT 1003 All Your Base
    Uva 1599 最佳路径
    Uva 10129 单词
    欧拉回路
    Uva 10305 给任务排序
    uva 816 Abbott的复仇
    Uva 1103 古代象形文字
    Uva 10118 免费糖果
    Uva 725 除法
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10506199.html
Copyright © 2020-2023  润新知