几乎超时,1800+ms,之前TLE了无数次,貌似是因为head后面写了MAXM然后memset多次用的时间太多了
此题为求最小割,但点数太大,注意到是平面图,可以转化为最短路径模型,详细方法可以看周冬的论文《两极相通——浅析最大—最小定理在信息学竞赛中的应用》
SPFA代码如下
#include <cstdio> #include <queue> #include <cstring> #define INF 0x3fffffff #define MAXN 200000 #define MAXM 1500010 using namespace std; int d[MAXN] ,head[MAXN], to[MAXM], next[MAXM], cost[MAXM], ecnt; bool vis[MAXN]; inline void addEdge(int u, int v, int w) { next[ecnt]=head[u];head[u]=ecnt; to[ecnt]=v;cost[ecnt++]=w; } void spfa(int S, int T){ for(int i = 0; i <= T; ++i) d[i] = INF; queue<int> Q; Q.push(S); vis[S]=1; d[S] = 0; while(!Q.empty()){ int u = Q.front(); Q.pop(); vis[u] = 0; for(int p = head[u]; p; p = next[p]){ if(d[to[p]] > d[u] + cost[p]){ d[to[p]] = d[u] + cost[p]; if(!vis[to[p]]){ vis[to[p]]=1; Q.push(to[p]); } } } } printf("%d\n",d[T]); } int main() { int T, i, j, x, n, ss, tt; scanf("%d",&T); while(T--){ scanf("%d",&n); ss = (n-1)*(n-1); tt = ss +1; memset(head, 0, (tt+1)*sizeof(int)); ecnt = 1; for(i = 0; i < n; ++i) for(j = 0; j < n; ++j){ scanf("%d",&x); if(j != n-1){ if(i == 0) addEdge(ss,i*(n-1)+j,x); else if(i == n-1) addEdge((i-1)*(n-1)+j,tt,x); else {addEdge(i*(n-1)+j,(i-1)*(n-1)+j,x);addEdge((i-1)*(n-1)+j,i*(n-1)+j,x);} } if(i != n-1){ if(j == 0) addEdge(i*(n-1)+j,tt,x); else if(j == n-1) addEdge(ss,i*(n-1)+j-1,x); else {addEdge(i*(n-1)+j,i*(n-1)+j-1,x);addEdge(i*(n-1)+j-1,i*(n-1)+j,x);} } } spfa(ss, tt); } return 0; }
下面是dijkstra+heap+STL的做法,原来是218ms,后来把scanf改成了getInt,立马变成93ms,这差距大得惊人啊……
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #define INF 0x3fffffff 5 #define MAXN 200000 6 #define MAXM 1500010 7 using namespace std; 8 9 int dis[MAXN] ,head[MAXN], to[MAXM], next[MAXM], cost[MAXM], ecnt; 10 bool vis[MAXN]; 11 12 inline void addEdge(int u, int v, int w) 13 { 14 next[ecnt]=head[u];head[u]=ecnt; 15 to[ecnt]=v;cost[ecnt++]=w; 16 } 17 18 void dijkstra(int s, int t) 19 { 20 for(int i = 0; i <= t; ++i) dis[i] = INF; 21 memset(vis,0,sizeof(vis)); 22 priority_queue<pair<int,int> > que; 23 dis[s] = 0; 24 que.push(make_pair(0,s)); 25 while(!que.empty()){ 26 int u = que.top().second; que.pop(); 27 if(vis[u]) continue; 28 vis[u] = true; 29 if(u == t) break; 30 for(int p = head[u]; p; p = next[p]){ 31 if(dis[to[p]] > dis[u] + cost[p]){ 32 dis[to[p]] = dis[u] + cost[p]; 33 que.push(make_pair(-dis[to[p]],to[p])); 34 } 35 } 36 } 37 printf("%d\n",dis[t]); 38 } 39 40 int getInt(){ 41 char ch=getchar(); 42 while(ch<'0'||ch>'9')ch=getchar(); 43 int num=0; 44 while(ch>='0'&&ch<='9'){ 45 num=num*10+ch-'0'; 46 ch=getchar(); 47 } 48 return num; 49 } 50 51 int main() 52 { 53 int T, i, j, x, n, ss, tt; 54 scanf("%d",&T); 55 while(T--){ 56 scanf("%d",&n); 57 ss = (n-1)*(n-1); tt = ss +1; 58 memset(head, 0, (tt+1)*sizeof(int)); 59 ecnt = 1; 60 for(i = 0; i < n; ++i) 61 for(j = 0; j < n; ++j){ 62 x = getInt(); //scanf("%d",&x); 63 if(j != n-1){ 64 if(i == 0) addEdge(ss,i*(n-1)+j,x); 65 else if(i == n-1) addEdge((i-1)*(n-1)+j,tt,x); 66 else {addEdge(i*(n-1)+j,(i-1)*(n-1)+j,x);addEdge((i-1)*(n-1)+j,i*(n-1)+j,x);} 67 } 68 if(i != n-1){ 69 if(j == 0) addEdge(i*(n-1)+j,tt,x); 70 else if(j == n-1) addEdge(ss,i*(n-1)+j-1,x); 71 else {addEdge(i*(n-1)+j,i*(n-1)+j-1,x);addEdge(i*(n-1)+j-1,i*(n-1)+j,x);} 72 } 73 } 74 dijkstra(ss, tt); 75 } 76 return 0; 77 }
后记:
后来为SPFA加入了其两个优化,先加入了优化SLF(Small Label First),时间降低至1343MS,后加入优化LLL(Large Label Last)时间降至562MS,再加入getInt,时间降至421MS
看来在这里还是比不上dijkstra+heap啊……
代码:
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #define INF 0x3fffffff 5 #define MAXN 200000 6 #define MAXM 1500010 7 #define LL long long 8 using namespace std; 9 10 int d[MAXN] ,head[MAXN], to[MAXM], next[MAXM], cost[MAXM], ecnt; 11 bool vis[MAXN]; 12 13 inline void addEdge(int u, int v, int w) 14 { 15 next[ecnt] = head[u]; head[u] = ecnt; 16 to[ecnt] = v; cost[ecnt++] = w; 17 } 18 19 void spfa(int S, int T){ 20 for(int i = 0; i <= T; ++i) d[i] = INF; 21 deque<int> Q; LL cntque = 1, sumque = 0; 22 Q.push_back(S); 23 vis[S]=1; 24 d[S] = 0; 25 while(!Q.empty()){ 26 int u = Q.front(); Q.pop_front(); 27 if(d[u] * cntque > sumque) {Q.push_back(u); continue;}//LLL optimization 28 sumque -= d[u]; cntque--; 29 vis[u] = 0; 30 for(int p = head[u]; p; p = next[p]){ 31 if(d[to[p]] > d[u] + cost[p]){ 32 d[to[p]] = d[u] + cost[p]; 33 if(d[to[p]] < d[Q.front()]){//SLF optimization 34 Q.push_front(to[p]); 35 sumque += d[to[p]]; cntque++; 36 } else 37 if(!vis[to[p]]){ 38 vis[to[p]]=1; 39 Q.push_back(to[p]); 40 sumque += d[to[p]]; cntque++; 41 } 42 } 43 } 44 } 45 printf("%d\n",d[T]); 46 } 47 48 int getInt(){ 49 char ch = getchar(); 50 while(ch<'0'||ch>'9')ch = getchar(); 51 int num = 0; 52 while(ch >= '0' && ch <= '9'){ 53 num = num*10 + ch - '0'; 54 ch = getchar(); 55 } 56 return num; 57 } 58 59 int main() 60 { 61 int T, i, j, x, n, ss, tt; 62 scanf("%d",&T); 63 while(T--){ 64 scanf("%d",&n); 65 ss = (n-1)*(n-1); tt = ss +1; 66 memset(head, 0, (tt+1)*sizeof(int)); 67 ecnt = 1; 68 for(i = 0; i < n; ++i) 69 for(j = 0; j < n; ++j){ 70 x = getInt();//scanf("%d",&x); 71 if(j != n-1){ 72 if(i == 0) addEdge(ss,i*(n-1)+j,x); 73 else if(i == n-1) addEdge((i-1)*(n-1)+j,tt,x); 74 else {addEdge(i*(n-1)+j,(i-1)*(n-1)+j,x);addEdge((i-1)*(n-1)+j,i*(n-1)+j,x);} 75 } 76 if(i != n-1){ 77 if(j == 0) addEdge(i*(n-1)+j,tt,x); 78 else if(j == n-1) addEdge(ss,i*(n-1)+j-1,x); 79 else {addEdge(i*(n-1)+j,i*(n-1)+j-1,x);addEdge(i*(n-1)+j-1,i*(n-1)+j,x);} 80 } 81 } 82 spfa(ss, tt); 83 } 84 return 0; 85 }