T1
可以证明每个点只会走一次
如果遇到环就在环的开始点打上标记
找到可行路的时候回溯,如果回溯时碰到有标记的点就输出Infinity!,否则直接输出ans就行
1 #include <cstdio> 2 int n,a[100010],b[100010],use[100010],in[100010],flag=0,incircle[100010]; 3 char ans[100010]; 4 int dfs(int x,int dep) 5 { 6 if (x<0||x>n-1) return 0; 7 if (x==n-1){ans[dep]=‘\0‘;flag=1;return 1;} 8 if (in[x]){incircle[x]=1;return 0;} 9 if (use[x]) return 0; 10 11 use[x]=1;in[x]=1; 12 ans[dep]=‘a‘; 13 if (dfs(x+a[x],dep+1)) 14 { 15 if (incircle[x]==1) flag=2; 16 return 1; 17 } 18 ans[dep]=‘b‘; 19 if (dfs(x+b[x],dep+1)) 20 { 21 if (incircle[x]==1) flag=2; 22 return 1; 23 } 24 in[x]=0; 25 return 0; 26 } 27 int main() 28 { 29 scanf("%d",&n); 30 for (int i=0;i<n;i++) scanf("%d",&a[i]); 31 for (int i=0;i<n;i++) scanf("%d",&b[i]); 32 dfs(0,0); 33 if (flag==0) printf("No solution!"); 34 if (flag==1) printf("%s",ans); 35 if (flag==2) printf("Infinity!"); 36 }
T2
由于这是一个稀疏图,所以可以直接跑3000次SPFA
枚举公共路径的两个端点即可,但是要考虑直接走两条最短路更优的情况,所以要初始化答案为两条最短路的路径和
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 struct E{ 6 int next,to; 7 }e[9000001]; 8 int n,m,a,b,sz=0,s1,t1,l1,s2,t2,l2,head[3001],x1,x2,f[3001][3001],que[3001],in[3001],top=-1,end=0,ans; 9 void push(int x) 10 { 11 top++; 12 if (top==3001) top=0; 13 que[top]=x; 14 } 15 int pop() 16 { 17 int ans=que[end]; 18 end++; 19 if (end==3001) end=0; 20 return ans; 21 } 22 bool empty() 23 { 24 return top+1==end; 25 } 26 void insert(int a,int b) 27 { 28 sz++; 29 e[sz].next=head[a]; 30 head[a]=sz; 31 e[sz].to=b; 32 } 33 int spfa(int s) 34 { 35 push(s);f[s][s]=0; 36 while(!empty()) 37 { 38 int x=pop();in[x]=0; 39 for (int i=head[x];i;i=e[i].next) 40 { 41 if (f[s][e[i].to]>f[s][x]+1) 42 { 43 f[s][e[i].to]=f[s][x]+1; 44 if (!in[e[i].to]) 45 { 46 in[e[i].to]=1; 47 push(e[i].to); 48 } 49 } 50 } 51 } 52 } 53 int main() 54 { 55 scanf("%d%d",&n,&m); 56 for (int i=1;i<=m;i++) 57 { 58 scanf("%d%d",&a,&b); 59 insert(a,b);insert(b,a); 60 } 61 scanf("%d%d%d",&s1,&t1,&l1); 62 scanf("%d%d%d",&s2,&t2,&l2); 63 memset(f,0x7f,sizeof(f)); 64 for (int i=1;i<=n;i++) spfa(i); 65 if (f[s1][t1]>l1||f[s2][t2]>l2) 66 { 67 printf("-1"); 68 return 0; 69 } 70 ans=f[s1][t1]+f[s2][t2]; 71 for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) 72 { 73 ans=min(ans,f[s1][i]+f[s2][i]+f[i][j]+f[j][t1]+f[j][t2]); 74 ans=min(ans,f[s1][i]+f[s2][j]+f[i][j]+f[j][t1]+f[i][t2]); 75 } 76 printf("%d",m-ans); 77 }
T3
时间: 2024-10-12 19:36:57