Codeforces Round#403 (Div. 1)
唉,昨天晚上迷迷糊糊地去打cf,结果fst两题,掉回蓝了...
A.Andryusha and Colored Balloons
题意:给定一棵树,任意两个距离小等于二的点不能染相同的颜色,求最小颜色数和染色方案。 n<=2*10^5
题解:求一个度数最大的点,度数+1即是颜色数,然后暴力染色。
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<map> #define ll long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } struct edge{ int to,next; }e[600005]; int head[600005]; int n,rt,cnt=0; bool b[600005]; int ans=0; int num[600005]; int col[600005]; int beg[600005]; void ins(int f,int t) { e[++cnt].next=head[f];head[f]=cnt; e[cnt].to=t; } void dfs(int x,int fa) { num[x]=1; for(int i=head[x];i;i=e[i].next) if(e[i].to!=fa) { dfs(e[i].to,x); num[x]++; } if(fa!=0)num[x]++; } void solve(int x,int fa) { // cout<<"solve"<<x<<" "<<fa<<" "<<col[x]<<" "<<col[fa]<<endl; int c=1; for(int i=head[x];i;i=e[i].next,c=c+1) if(!col[e[i].to]) { while(c==col[x]||c==col[fa])c=c+1; col[e[i].to]=c; solve(e[i].to,x); } else c--; } int main() { n=read(); for(int i=1;i<n;i++) {int u=read(),v=read();ins(u,v);ins(v,u);} dfs(1,0);for(int i=1;i<=n;i++)if(num[i]>ans){ans=num[i];rt=i;} col[rt]=1;solve(rt,0);printf("%d\n",ans); for(int i=1;i<=n;i++)printf("%d ",col[i]); return 0; }
B.Innokenty and a Football League
题意:有n个足球队,每个队有两个选名字的方案,也就是直接给定了两个名字。所有球队不能有相同的名字。
特殊的,如果有两个球队第一个名字相同,一个球队选了第二个名字,另一个球队不能选第一个名字。n<=1000
题解:2-sat
据说有个学长188行大暴力过了,真的佩服。
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<map> #define ll long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } int n,dn=0; char ch[10005][5]; char s[10005]; int h1[10005],h2[10005],q[20005]; bool inq[10005]; struct edge{ int to,next; }e[8000000]; int head[10005],dfn[10005],low[10005],bel[10005],col[10005],in[10005]; int cnt=0,cc,top=0,cft[10005]; queue<int> qu; void ins(int f,int t) { e[++cnt].next=head[f];head[f]=cnt; e[cnt].to=t; } void hashh(int k) { // cout<<k<<" "<<ch[k][1]<<" "<<ch[k][2]<<" "<<ch[k][3]<<" "<<ch[k][4]<<endl; int hash1,hash2; hash1=hash2=(ch[k][1]-'A')*26+ch[k][2]-'A'; hash1=hash1*26+(ch[k][3]-'A'); hash2=hash2*26+(ch[k][4]-'A'); h1[k]=hash1;h2[k]=hash2; } void tj(int x) { //cout<<"tj"<<x<<endl; dfn[x]=low[x]=++dn;inq[x]=1;q[++top]=x; for(int i=head[x];i;i=e[i].next) { int v=e[i].to; if(!dfn[v]){tj(v);low[x]=min(low[x],low[v]);} else {if(inq[v])low[x]=min(low[x],dfn[v]);} } if(dfn[x]==low[x]) for(++cc;q[top+1]!=x;bel[q[top]]=cc,inq[q[top]]=0,top--); } void rebuild() { for(int i=1;i<=n<<1;i++) for(int j=head[i];j;j=e[j].next) if(bel[i]!=bel[e[j].to]) ins(bel[i],bel[e[j].to]),in[e[j].to]++; } void topsort() { for(int i=n*2+1;i<=cc;i++) if(in[i]==0) qu.push(i); while(!qu.empty()) { int u=qu.front();qu.pop(); if(!col[u]) for(int j=1;j<=n<<1;j++) if(bel[j]==u) col[bel[j>n?j-n:j+n]]=1; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; --in[v]; if(!in[v]) qu.push(v); } } } int main() { n=read();cc=n<<1; for(int i=1;i<=n;i++) { scanf("%s",s+1); ch[i][1]=s[1];ch[i][2]=s[2];ch[i][3]=s[3]; scanf("%s",s+1);ch[i][4]=s[1]; hashh(i); } for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) { if(h1[i]==h1[j]&&h2[i]==h2[j]) return 0*puts("NO"); if(h1[i]==h1[j]){ins(i,j+n);ins(j,i+n);ins(i+n,j+n);ins(j+n,i+n);} if(h1[i]==h2[j]){ins(i,j);ins(j+n,i+n);} if(h2[i]==h1[j]){ins(i+n,j+n);ins(j,i);} if(h2[i]==h2[j]){ins(i+n,j);ins(j+n,i);} } for(int i=1;i<=n*2;i++)if(!dfn[i])tj(i); //for(int i=1;i<=n;i++)cout<<bel[i]<<" "<<bel[i+n]<<endl; for(int i=1;i<=n;i++)if(bel[i]==bel[i+n])return 0*puts("NO"); rebuild(); topsort(); puts("YES"); for(int i=1;i<=n;i++)if(col[bel[i]]==0)printf("%c%c%c\n",ch[i][1],ch[i][2],ch[i][3]); else printf("%c%c%c\n",ch[i][1],ch[i][2],ch[i][4]); return 0; }
C.Underground Lab
题意:给定一个n个点m条边的连通图,然后你要用k条路径覆盖所有的点,每条路径最多2*n/k向上取整个点,求一个方案。n<=2*10^5
题解:假装它是一棵树,然后求一个欧拉序列,只有2*n-1个点,然后分段输出就行了。
注意处理输出之后不足k组的情况,乱填充一下就行。
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<map> #define ll long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } int ans[400005]; bool b[400005]; struct edge{ int to,next; }e[800005]; int head[400005]; int n,m,k,cnt=0,top=0,q[500005]; void ins(int f,int t) { e[++cnt].next=head[f];head[f]=cnt; e[cnt].to=t; } void dfs(int x,int fa) { b[x]=1;q[++top]=x; for(int i=head[x];i;i=e[i].next) if(!b[e[i].to]) { dfs(e[i].to,x); q[++top]=x; } } int main() { n=read();m=read();k=read(); for(int i=1;i<=m;i++) {int u=read(),v=read();ins(u,v);ins(v,u);} dfs(1,0); int l=(top+k-1)/k; int i=1; for(int pre=0;i<=k&&pre<top;i++,pre+=l) { int l2=min(l,top-pre); printf("%d ",l2); for(int j=1;j<=l2;j++) printf("%d ",q[pre+j]); puts(""); } while(i<=k){i++;printf("1 1\n");} return 0; }
D.Axel and Marston in Bitland
给丁一个n点m边的图,然后每条边有一个类别1或者0。
你要按照给定的顺序走边:一条0的,然后把刚走的取反接起来,然后一直做。比如P代表0,B代表1,那么你要这么走:
P, PB, PBBP, PBBPBPPB, PBBPBPPBBPPBPBBP, and so on.
求最多能走多少条。如果答案>10^18,输出-1 n<=500
题解:倍增,用bitset来求出长度为k,开头是0或者1,所有点对的连通性,然后dp
用f[k][i][0/1]表示开头是0/1,第i个点,最后一次走的长度是2^k的最大距离。
复杂度:
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<map> #include<bitset> #define ll long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } bitset<505> s[2][502][62]; ll f[2][502][62]; int n,m; int main() { n=read();m=read(); for(int i=1;i<=m;i++) { int u=read(),v=read(),w=read(); s[w][u][0][v]=1; } for(int k=0;k<60;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(s[0][i][k][j])s[0][i][k+1]|=s[1][j][k]; if(s[1][i][k][j])s[1][i][k+1]|=s[0][j][k]; } memset(f,128,sizeof(f));f[0][1][61]=0; for(int k=60;k>=0;k--) { for(int i=1;i<=n;i++) { f[0][i][k]=f[0][i][k+1]; f[1][i][k]=f[1][i][k+1]; } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(s[1][i][k][j]) f[0][j][k]=max(f[0][j][k],f[1][i][k+1]+(1LL<<k)); if(s[0][i][k][j]) f[1][j][k]=max(f[1][j][k],f[0][i][k+1]+(1LL<<k)); } } } ll mx=0; for(int i=1;i<=n;i++)mx=max(mx,max(f[1][i][0],f[0][i][0])); if(mx>=1000000000000000000LL)puts("-1"); else printf("%I64d\n",mx); return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步