Codeforces Round #290 (Div. 2)
C题:给你n个字符串要求你重新排列小写字母的字典序,要求使给的字符串按字典序从小到大排列。
思路:很容易想到相邻两串找到第一个不相同的建边,然后跑拓扑序就好啦。
1 #include<bits/stdc++.h> 2 #define fi first 3 #define se second 4 #define mk make_pair 5 #define pii pair<int,int> 6 #define read(x) scanf("%d",&x) 7 #define sread(x) scanf("%s",x) 8 #define dread(x) scanf("%lf",&x) 9 #define lread(x) scanf("%lld",&x) 10 using namespace std; 11 12 typedef long long ll; 13 const int inf=0x3f3f3f3f; 14 const ll INF=0x3f3f3f3f3f3f3f3f; 15 const int N=2000+7; 16 const int M=12; 17 18 char s[105][105]; 19 int len[105],topo[30],n,tot; 20 int vis[30]; 21 22 vector<int> edge[30]; 23 24 bool dfs(int u) 25 { 26 vis[u]=-1; 27 for(int v:edge[u]) 28 { 29 if(vis[v]==-1) 30 return false; 31 if(vis[v]==0 && !dfs(v)) 32 return false; 33 } 34 topo[tot--]=u; 35 vis[u]=1; 36 return true; 37 } 38 bool topo_sort() 39 { 40 tot=25; 41 for(int i=0;i<26;i++) 42 if(!vis[i] && !dfs(i)) 43 return false; 44 return true; 45 } 46 int main() 47 { 48 read(n); 49 for(int i=1;i<=n;i++) 50 sread(s[i]+1),len[i]=strlen(s[i]+1); 51 52 for(int i=1;i<n;i++) 53 { 54 bool flag=false; 55 for(int j=1;j<=len[i] && j<=len[i+1];j++) 56 { 57 if(s[i][j]!=s[i+1][j]) 58 { 59 edge[s[i][j]-'a'].push_back(s[i+1][j]-'a'); 60 flag=true; 61 break; 62 } 63 } 64 if(!flag && len[i]>len[i+1]) 65 { 66 puts("Impossible"); 67 return 0; 68 } 69 } 70 if(!topo_sort()) 71 puts("Impossible"); 72 else 73 { 74 for(int i=0;i<26;i++) 75 printf("%c",topo[i]+'a'); 76 puts(""); 77 } 78 return 0; 79 } 80 /* 81 */
D题:有n个距离,选择一个距离都有一个花费,当你选择一条距离x的时候,你就能向左或者向右跳x格,问你最少花费多少就能
跳到数轴上任意位置。
思路:题目可以转化为要你选出一些距离,这些距离的gcd为1,最小花费为多少。 然后用map dp就行了。 dp[ i ]表示gcd为 i 时的最小花费。
1 #include<bits/stdc++.h> 2 #define fi first 3 #define se second 4 #define mk make_pair 5 #define ll long long 6 #define pll pair<ll,ll> 7 #define pil pair<int,ll> 8 #define pli pair<ll,int> 9 #define pii pair<int,int> 10 #define read(x) scanf("%d",&x) 11 #define sread(x) scanf("%s",x) 12 #define dread(x) scanf("%lf",&x) 13 #define lread(x) scanf("%lld",&x) 14 using namespace std; 15 16 const int N=300+7; 17 const int M=2e6+7; 18 const int inf=0x3f3f3f3f; 19 const ll INF=0x3f3f3f3f3f3f3f3f; 20 const int mod=1e9+7; 21 22 int n; 23 pii a[N]; 24 map<int,int> dp; 25 int main() 26 { 27 read(n); 28 for(int i=1;i<=n;i++) 29 read(a[i].fi); 30 31 for(int i=1;i<=n;i++) 32 read(a[i].se); 33 34 dp[0]=0; 35 map<int,int> :: iterator it; 36 for(int i=1;i<=n;i++) 37 { 38 int x=a[i].fi; 39 int c=a[i].se; 40 for(it=dp.begin(); it!=dp.end(); it++) 41 { 42 int y=it->first; 43 int d=__gcd(x,y); 44 int tmp=it->second+c; 45 if(dp[d] && dp[d]<tmp) 46 continue; 47 dp[d]=tmp; 48 } 49 } 50 if(!dp[1]) 51 puts("-1"); 52 else 53 printf("%d ",dp[1]); 54 return 0; 55 } 56 /* 57 */
E题:让你把n个数安排到任意个圆桌上,要求相邻的两个数加起来是素数。
思路:最大流,因为没有1,所以只有奇数和偶数相邻时才能为素数。 然后我们从原点向奇数建权值为2的边,偶数向
汇点建权值为2的边,然后加起来是素数的对应的奇数偶数之间建一条权值为1的边,跑最大流,看最大流是不是n。
1 #include<bits/stdc++.h> 2 #define fi first 3 #define se second 4 #define mk make_pair 5 #define pii pair<int,int> 6 #define read(x) scanf("%d",&x) 7 #define sread(x) scanf("%s",x) 8 #define dread(x) scanf("%lf",&x) 9 #define lread(x) scanf("%lld",&x) 10 using namespace std; 11 12 typedef long long ll; 13 const int inf=0x3f3f3f3f; 14 const ll INF=0x3f3f3f3f3f3f3f3f; 15 const int N=200+7; 16 const int M=12; 17 18 int n,S,T,tot,cnt,a[N],head[N],level[N]; 19 bool vis[N]; 20 21 vector<int> vec[N],ans[N]; 22 23 struct edge 24 { 25 int f,t,v,nx; 26 }e[N*N]; 27 28 void add(int f,int t,int v) 29 { 30 e[tot].f=f; e[tot].t=t; e[tot].v=v; 31 e[tot].nx=head[f]; head[f]=tot++; 32 33 e[tot].f=t; e[tot].t=f; e[tot].v=0; 34 e[tot].nx=head[t]; head[t]=tot++; 35 } 36 37 bool bfs() 38 { 39 memset(level,0,sizeof(level)); 40 queue<int> Q; 41 Q.push(S); level[S]=1; 42 43 while(!Q.empty()) 44 { 45 int u=Q.front(); Q.pop(); 46 if(u==T) 47 return true; 48 49 for(int i=head[u];~i;i=e[i].nx) 50 { 51 int v=e[i].t; 52 if(level[v] || !e[i].v) 53 continue; 54 55 level[v]=level[u]+1; 56 Q.push(v); 57 } 58 59 } 60 return false; 61 } 62 63 int dfs(int u,int p) 64 { 65 if(u==T) 66 return p; 67 int ret=0; 68 for(int i=head[u];~i;i=e[i].nx) 69 { 70 int v=e[i].t; 71 if(level[v]!=level[u]+1 || !e[i].v) 72 continue; 73 int f=dfs(v,min(p-ret,e[i].v)); 74 ret+=f; 75 e[i].v-=f; 76 e[i^1].v+=f; 77 if(ret==p) 78 break; 79 } 80 if(!ret) 81 level[u]=0; 82 return ret; 83 } 84 85 int Dinic() 86 { 87 int ans=0; 88 while(bfs()) 89 ans+=dfs(S,inf); 90 return ans; 91 } 92 93 void cal(int u,int op) 94 { 95 vis[u]=true; 96 ans[op].push_back(u); 97 for(int v:vec[u]) 98 if(!vis[v]) 99 cal(v,op); 100 } 101 102 bool is_prime(int x) 103 { 104 for(int i=2;i*i<=x;i++) 105 if(x%i==0) 106 return false; 107 return true; 108 } 109 110 int main() 111 { 112 memset(head,-1,sizeof(head)); 113 read(n); 114 for(int i=1;i<=n;i++) 115 read(a[i]); 116 117 S=0,T=n+1; 118 119 for(int i=1;i<=n;i++) 120 { 121 if(a[i]&1) 122 add(S,i,2); 123 else 124 add(i,T,2); 125 } 126 127 for(int i=1;i<=n;i++) 128 for(int j=1;j<=n;j++) 129 if(a[i]&1 && is_prime(a[i]+a[j])) 130 add(i,j,1); 131 132 int ret=Dinic(); 133 134 if(ret!=n) 135 puts("Impossible"); 136 else 137 { 138 for(int i=0;i<tot;i++) 139 { 140 if(e[i].f==S || e[i].t==S || e[i].f==T || e[i].t==T) 141 continue; 142 143 if(a[e[i].f]%2==1 && e[i].v==0) 144 { 145 vec[e[i].f].push_back(e[i].t); 146 vec[e[i].t].push_back(e[i].f); 147 } 148 } 149 for(int i=1;i<=n;i++) 150 if(!vis[i]) 151 cal(i,cnt++); 152 printf("%d ",cnt); 153 for(int i=0;i<cnt;i++) 154 { 155 printf("%d ",ans[i].size()); 156 for(int j:ans[i]) 157 printf("%d ",j); 158 puts(""); 159 } 160 } 161 return 0; 162 } 163 /* 164 */