POJ 2375 强联通缩点+判断
2014-09-26 16:52
239 查看
题意:给你一个矩阵,让你加最少的双向边使得任意两个点之间都可以互达。
分析:强联通缩点,缩点之后如果没有边,则输出点数-1,否则输出入度为0的点数和出度为0的点数的最大值。
代码:
分析:强联通缩点,缩点之后如果没有边,则输出点数-1,否则输出入度为0的点数和出度为0的点数的最大值。
代码:
#pragma comment(linker,"/STACK:102400000,102400000") #include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #include <vector> #include <string> #include <math.h> #include <queue> #include <stack> #include <map> #include <set> using namespace std; typedef long long ll; //ŒÇµÃ±ØÒªµÄʱºòžÄ³ÉÎÞ·ûºÅ const int maxn=250005; //µãÊý const int maxm=1000005; //±ßÊý const int INF=1000000000; struct EdgeNode { int from; int to; int next; }edge[maxm]; int head[maxn],cnt; void add(int x,int y) { edge[cnt].from=x;edge[cnt].to=y;edge[cnt].next=head[x];head[x]=cnt++; //printf("%d %d\n",x,y); } void init() { cnt=0; memset(head,-1,sizeof(head)); } int dfn[maxn],low[maxn],ins[maxn],cixu,scc_count,n,ru[maxn],chu[maxn],sd[maxn]; stack<int>S; void dfs(int u) { int v,x; dfn[u]=low[u]=++cixu; S.push(u); ins[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) { v=edge[i].to; if(!dfn[v]){ dfs(v); low[u]=min(low[u],low[v]); } else if(ins[v]) //Èç¹ûÒÑŸËѹý£¬²¢ÇÒÔÚÕ»ÀïÃ棬Èç¹û²»ÔÚÕ»ÀïÃ棬˵Ã÷žÃµãÊôÓÚÆäËûµÄÇ¿Á¬Íš·ÖÁ¿ÀïÃæ low[u]=min(low[u],dfn[v]); //ŽËŽŠlowŽúÌædfnÒ²ÊÇ¿ÉÒԵģ¬µ«ÊÇÔÚtarjanÇóÎÞÏòÍŒµÄʱºò²»ÄÜ } if(dfn[u]==low[u]) //±íÊŸuΪŽËÇ¿Á¬Íš·ÖÁ¿µÚÒ»žö±»·¢Ïֵĵ㣬ÊôÓÚžÃÇ¿Á¬Íš·ÖÁ¿µÄËùÓеÄÆäËûµã¶ŒÔÚÕ»ÖУ¬ËûµÄÉÏÃæ { scc_count++; do { x=S.top(); S.pop(); sd[x]=scc_count; ins[x]=0; }while(x!=u); } } void tarjan(int n) { for(int i=1;i<=n;i++)sd[i]=i; //Ëõµã±êŒÇÊý×é memset(ins,0,sizeof(ins)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); cixu=scc_count=0; for(int i=1;i<=n;i++) //¿ÉÄÜËùžøµÄ͌Ϊ²»Á¬ÍšµÄÍŒ£¬·Ö¿é£¬ÒòŽËÐèÒª±éÀúËùÓеĵã { if(!dfn[i]) dfs(i); } } void SD() { int x,y,len=cnt; init(); memset(ru,0,sizeof(ru)); memset(chu,0,sizeof(chu)); for(int i=0;i<len;i++){ x=sd[edge[i].from]; y=sd[edge[i].to]; if(x==y)continue; add(x,y); chu[x]++; ru[y]++; } } int mp[505][505],js[505][505],ans,m; int d[5][3]={{-1,0},{1,0},{0,-1},{0,1}}; int yj(int x,int y) { if(x<1||x>m||y<1||y>n)return 1; return 0; } void build() { init(); int i,j,k,x,y; for(i=1;i<=m;i++){ for(j=1;j<=n;j++){ for(k=0;k<4;k++){ x=i+d[k][0]; y=j+d[k][1]; if(yj(x,y))continue; if(mp[i][j]>=mp[x][y])add(js[i][j],js[x][y]); } } } } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int i,j,rds,cds; while(~scanf("%d%d",&n,&m)) { ans=0; for(i=1;i<=m;i++){ for(j=1;j<=n;j++){ js[i][j]=++ans; scanf("%d",&mp[i][j]); } } build(); tarjan(ans); SD(); rds=cds=0; for(i=1;i<=scc_count;i++){ if(ru[i]==0)rds++; if(chu[i]==0)cds++; } if(rds==cds&&rds==scc_count)printf("%d\n",rds-1); else printf("%d\n",max(rds,cds)); } return 0; }
相关文章推荐
- POJ 2186 强联通缩点+判断+找出度为0的点
- POJ 2762判断单联通(强连通缩点+拓扑排序)
- POJ 2762 Going from u to v or from v to u? Tarjan缩点+判断链
- POJ 1236 Network of Schools ★(经典问题:强联通分量+缩点)
- poj 2942 求点双联通+二分图判断奇偶环+交叉染色法判断二分图
- poj 2942 (点双联通+判断二分图)
- poj 2942 Knights of the Round Table Tarjan求点双联通分量+黑白染色二分图判断
- POJ 1236 Network of Schools ★(经典问题:强联通分量+缩点)
- POJ 1236 Network of School(强联通缩点)
- poj 2513 欧拉回路+并查集判断是否联通+Trie树
- poj 2762 Going from u to v or from v to u? (判断是否是弱联通图)
- (判断是否为弱联通分量) poj 2762
- POJ 2553 Tarjan缩点+判断出度为0
- POJ 2762 强联通缩点+拓扑排序
- POJ 3160 强联通缩点+dp
- poj 2942 求点双联通+二分图判断奇偶环+交叉染色法判断二分图
- poj 3694双联通缩点+LCA
- POJ 2762 强连通 + 缩点+判断入度出度
- poj 2762 Going from u to v or from v to u? (强联通分量缩点 + 欧拉回路或通路)
- poj1979 Red and Black(dfs判断联通分量)