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
",ans*(-1));
173     }
174     return 0;
175 }
原文地址:https://www.cnblogs.com/assult/p/3881547.html