poj 3592 Instantaneous Transference 强连通图 缩点 再求最长路
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<stack> 5 #include<queue> 6 using namespace std; 7 #define maxx 44 8 #define maxx2 44*44 9 #define INF 99999999 10 char s[maxx][maxx]; 11 bool tong[maxx2][maxx2],vis[maxx2]; 12 int xing[maxx2],n,m,pre[maxx2],scc_num[maxx2],c,value[maxx2],low[maxx2],scc_count,scc_value[maxx2],d[maxx2]; 13 vector<int > g[maxx2],reg[maxx2]; 14 stack<int > sta; 15 16 void dfs(int u) 17 { 18 low[u]=pre[u]=c++; 19 sta.push(u);//!!!!!!注意 20 for(int i=0; i<g[u].size(); i++) 21 { 22 int v=g[u][i]; 23 if(!pre[v]) 24 { 25 dfs(v); 26 low[u]=min(low[u],low[v]); 27 } 28 else if(!scc_num[v]) 29 low[u]=min(low[u],pre[v]); 30 } 31 if(low[u]==pre[u]) 32 { 33 scc_count++; 34 while(1) 35 { 36 int t=sta.top(); 37 sta.pop(); 38 scc_num[t]=scc_count; 39 if(t==u) 40 break; 41 } 42 } 43 } 44 void tranjan(int n) 45 { 46 memset(pre,0,sizeof(pre)); 47 memset(scc_num,0,sizeof(scc_num)); 48 memset(scc_value,0,sizeof(scc_value)); 49 c=1; 50 scc_count=0; // 强连通个数 1-----scc_count 51 for(int i=0; i<n; i++) 52 { 53 if(pre[i]==0) 54 dfs(i); 55 } 56 for(int i=0; i<n; i++) 57 scc_value[scc_num[i]]+=value[i]; 58 ////////////////////重新构图 点为1 到 scc_count 59 for(int u=0; u<n; u++) 60 for(int i=0; i<g[u].size(); i++) 61 { 62 int v=g[u][i]; 63 if(scc_num[u]!=scc_num[v])//没在同一个连通分量里 64 { 65 int uu,vv; 66 uu=scc_num[u]; 67 vv=scc_num[v]; 68 reg[uu].push_back(vv); 69 } 70 } 71 } 72 73 int spfa(int s,int n,int w) 74 { 75 queue<int> q; 76 memset(vis,false,sizeof(vis)); 77 memset(d,0,sizeof(d)); 78 d[s]=w*(-1); 79 q.push(s); 80 vis[s]=true; 81 while(!q.empty()) 82 { 83 int u,v; 84 u=q.front(); 85 q.pop(); vis[u]=false; 86 for(int i=0; i<reg[u].size(); i++) 87 { 88 v=reg[u][i]; 89 if(d[v]>(d[u]-scc_value[v])) 90 { 91 d[v]=d[u]-scc_value[v]; 92 if(!vis[v]) 93 { 94 q.push(v); 95 vis[v]=true; 96 } 97 } 98 } 99 } 100 int minn=d[s]; 101 for(int i=1; i<=n; i++) 102 103 if(d[i]<minn) 104 minn=d[i]; 105 return minn; 106 } 107 108 int main() 109 { 110 int a,b,i,j,t,temp; 111 scanf("%d",&t); 112 while(t--) 113 { 114 scanf("%d%d",&n,&m); 115 memset(tong,false,sizeof(tong)); 116 for(i=0; i<=n*m; i++) 117 { 118 g[i].clear(); 119 reg[i].clear(); 120 } 121 int num=0; 122 for(i=0; i<n; i++) 123 { 124 scanf("%s",s[i]); 125 for(j=0; j<m; j++) 126 if( s[i][j]=='*' ) 127 xing[num++]=i*m+j; 128 } 129 for(i=0; i<n*m; i++) 130 { 131 a=i/m; 132 b=i%m; 133 if(s[a][b]=='#') 134 value[i]=-INF; 135 else if(s[a][b]=='*') 136 value[i]=0; 137 else 138 value[i]=s[a][b]-'0'; 139 if(a+1<n) 140 { 141 temp=(a+1)*m+b; 142 if(s[a+1][b]!='#') 143 { 144 g[i].push_back(temp); 145 tong[i][temp]=true; 146 } 147 } 148 if(b+1<m) 149 { 150 temp=a*m+b+1; 151 if(s[a][b+1]!='#') 152 { 153 g[i].push_back(temp); 154 tong[i][temp]=true; 155 } 156 } 157 } 158 for(i=0; i<num; i++) 159 { 160 scanf("%d%d",&a,&b); 161 temp=a*m+b; 162 if(s[a][b]!='#') 163 { 164 g[xing[i]].push_back(temp); 165 tong[xing[i]][temp]=true; 166 } 167 } 168 tranjan(m*n);// 求 强连通 再缩点 169 int ans,startpoint; 170 startpoint=scc_num[0]; 171 ans=spfa(startpoint,scc_count,scc_value[startpoint]); // 对新图求最短路 172 printf("%d\n",ans*(-1)); 173 } 174 return 0; 175 }