多校 2013 4
A
区间DP
#include<stdio.h> #include<string.h> #include<algorithm> #include<string> #include<iostream> using namespace std; #define MAXN 1009 #define inf 10007 typedef __int64 ll; char s[MAXN]; int dp[MAXN][MAXN]; int main() { int t,ca; scanf("%d",&t); ca=1; while(t--) { scanf("%s",s+1); int len=strlen(s+1); for(int i=1;i<=len;i++) dp[i][i]=1; for(int l=1;l<=len;l++) { for(int j=1;j+l-1<=len;j++) { int en=j+l-1; dp[j][en]=(dp[j+1][en]+dp[j][en-1]-dp[j+1][en-1]+inf)%inf; if(s[j]==s[en]) dp[j][en]=(dp[j][en]+dp[j+1][en-1]+1)%inf; } } printf("Case %d: %d ",ca++,dp[1][len]); } return 0; }
D
强连通 有一点点逆向思维 去掉的边 是缩点 的入度或者出度为0 num[i]*(n-num[i]) 最小
#include<stdio.h> #include<string.h> #include<algorithm> #include<string> #include<iostream> #include<stack> using namespace std; #define MAXN 100109 #define inf 1e12+7 typedef __int64 ll; int head[MAXN],dfn[MAXN],low[MAXN],fa[MAXN],c1[MAXN],in[MAXN],out[MAXN]; int k,cnt,num; bool vis[MAXN]; stack<int>s; struct node { int next,v,u; }edge[MAXN]; void add(int u,int v) { edge[cnt].v=v; edge[cnt].u=u; edge[cnt].next=head[u]; head[u]=cnt++; } void dfs(int u) { low[u]=dfn[u]=k++; vis[u]=1; s.push(u); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(!dfn[v]) { dfs(v); low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { num++; while(!s.empty()) { int now=s.top(); s.pop(); vis[now]=0; fa[now]=num; c1[num]++; if(now==u) break; } } } int main() { int t; scanf("%d",&t); int ca=1; while(t--) { int n,m; scanf("%d%d",&n,&m); memset(head,-1,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(c1,0,sizeof(c1)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); cnt=0; for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); add(a,b); } num=0; k=1; for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i); printf("Case %d: ",ca++); if(num==1) printf("-1 "); else { for(int i=0;i<cnt;i++) { if(fa[edge[i].u]!=fa[edge[i].v]) { in[fa[edge[i].v]]++; out[fa[edge[i].u]]++; } } ll mx=0; //printf("%d ",num); for(int i=1;i<=num;i++) { //printf("in %d out %d ",in[i],out[i]); if(in[i]==0||out[i]==0) { mx=max(mx,(ll)n*(n-1)-m-(ll)c1[i]*(n-c1[i])); } } printf("%I64d ",mx); } } return 0; }