Codeforces Round #290 (Div. 1) A,B,C题解

掉分了...比赛中各种莫名其妙的错误都犯了...

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

A.Fox And Names

给你一些字符串,让你给出字母的字典序,使得给出的字符串按照升序排序


直接按照给你的顺序构图然后拓扑。第一次提交后我忘记考虑car<ca这种是Impossible的情况了。想重交结果发现已经被HACK了...房间那两个人总共hack成功了19次...

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

B.Fox And Jumping

给你一些数,每个数有一个价值,要求最小价值选出若干数使得gcd为1


f[i][j]表示前i个,gcd为j的最小代价。转移就

x=gcd(a[k],j);

f[i][x]=min(f[i-1][x]+c[i],f[i-1][x]);

*此处的第二维可以写个hash或者直接用map维护

复杂度大概是n*n*1700的,可以过

当时写出来了。后来发现我多了一重没用的n循环。删掉后发现不对。赛后才发现是f[i][j]没有初始化传递f[i-1][j]。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

C.Fox And Dinner

给你若干个数,让你分成k组,每组围成一个圆,使得相邻两个数和均为素数,且每组人数应>=3个。输出方案


看到没什么人交就觉得这题超出自己能力范围了,结果就是个裸的最大流

因为素数肯定是一奇一偶相加,因此,我们可以

S向奇数连流量为2的边

偶数向T连流量为2的边

对于奇偶之和为质数的两个点,奇数向偶数连流量为1的边

然后跑最大流。

如果所有S连向奇数和偶数连向T的边都满流,则存在方案。

对于输出方案我们可以直接dfs求出。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

A.Fox And Names

#include<cmath>
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct line
{
     int s,t;
     int next;
}a[1000001];
int head[10001];
int edge;
inline void add(int s,int t)
{
	 a[edge].next=head[s];
     head[s]=edge;
     a[edge].s=s;
     a[edge].t=t;
}
string x[100001];
int dis[100001];
int indeg[10001],outdeg[10001];
int ans[10001];
queue <int> Q;
int main()
{
     int n;
     scanf("%d",&n);
     int i,j;
     for(i=1;i<=n;i++)
          cin>>x[i];
     int k1,k2,l1,l2;
     for(i=1;i<=n;i++)
     {
          for(j=i+1;j<=n;j++)
          {
               l1=x[i].size();
               l2=x[j].size();
               k1=0;
               k2=0;
               while(k1<l1&&k2<l2)
               {
               	    if(x[i][k1]!=x[j][k2])
               	    {
               	         edge++;
               	         add(x[i][k1]-'a'+1,x[j][k2]-'a'+1);
               	         indeg[x[j][k2]-'a'+1]++;
               	         outdeg[x[i][k1]-'a'+1]++;
               	         break;
               	    }
                    k1++;
                    k2++;
               }
               if(l2<l1&&k2==l2)
               {
                    printf("Impossible\n");
                    return 0;
               }
          }
     }
     int sum=0;
     int p=0;
     for(i=1;i<=26;i++)
     {
          if(indeg[i]==0&&outdeg[i]!=0)
          {
               Q.push(i);
               p++;
               ans[p]=i;
               dis[i]=1;
          }
     }
     bool flag=true;
     while(!Q.empty())
     {
     	  int d=Q.front();
     	  Q.pop();
          for(i=head[d];i!=0;i=a[i].next)
          {
          	   int t=a[i].t;
               if(dis[t]==1)
               {
                    flag=false;
                    break;
               }
               else
               {
                    indeg[t]--;
                    if(indeg[t]==0)
                    {
                         dis[t]=1;
                         Q.push(t);
                         p++;
                         ans[p]=t;
                    }
               }
          }
     }
     for(i=1;i<=26;i++)
     {
          if(dis[i]==0&&indeg[i]==0)
          {
               Q.push(i);
               p++;
               ans[p]=i;
               dis[i]=1;
          }
          else if(dis[i]==0)
          {
               printf("Impossible\n");
               return 0;
          }
     }
     for(i=1;i<=p;i++)
          printf("%c",ans[i]+'a'-1);
     printf("\n");
     return 0;
     return 0;
}

B. Fox And Jumping

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
map <int,int> st;
int p;
int fx[100001];
int f[301][100001];
int l[301],c[301];
inline int gcd(int x,int y)
{
     int m=x%y;
     while(m!=0)
     {
          x=y;
          y=m;
          m=x%y;
     }
     return y;
}
int main()
{
     int n;
     scanf("%d",&n);
     int i,j,k;
     int x;
     for(i=1;i<=n;i++)
     {
          scanf("%d",&l[i]);
          x=l[i];
          for(j=1;j<=sqrt(x);j++)
          {
          	   if(x%j!=0)
          	        continue;
               k=x/j;
               if(st[j]==0)
               {
                    p++;
                    st[j]=p;
                    fx[p]=j;
               }
               if(st[k]==0)
               {
                    p++;
                    st[k]=p;
                    fx[p]=k;
               }
          }
     }
     sort(fx+1,fx+1+p);
     for(i=1;i<=p;i++)
          st[fx[i]]=i;
     for(i=1;i<=n;i++)
          scanf("%d",&c[i]);
     memset(f,127/3,sizeof(f));
     int nox=f[1][1];
     for(i=1;i<=n;i++)
     {
     	  f[i][st[l[i]]]=min(c[i],f[i-1][st[l[i]]]);
          //for(k=1;k<=i-1;k++)
          //{
          	   for(j=1;j<=p;j++)
                    f[i][j]=min(f[i-1][j],f[i][j]);
               for(j=1;j<=p;j++)
               {
               	    int tx=gcd(fx[j],l[i]);
               	    int kx=st[tx];
					f[i][kx]=min(f[i][kx],f[i-1][j]+c[i]);
					f[i][kx]=min(f[i][kx],f[i-1][kx]);
               }
          //}
     }

     if(f[n][st[1]]==nox)
          printf("-1\n");
     else
          printf("%d\n",f[n][st[1]]);
     return 0;
}

C. Fox And Dinner

#include<cmath>
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
struct line
{
     int s,t;
     int f;
     int next;
}a[100001];
int head[1001];
int edge;
inline void add(int s,int t,int f)
{
     a[edge].next=head[s];
     head[s]=edge;
     a[edge].s=s;
     a[edge].t=t;
     a[edge].f=f;
}
int p;
inline bool pd(int x)
{
	 if(x==1)
	      return false;
     int i;
     bool flag=true;
     for(i=2;i<=sqrt(x);i++)
     {
          if(x%i==0)
          {
               flag=false;
               break;
          }
     }
     return flag;
}
queue <int>Q;
int pt[100001];
inline bool bfs(int st,int tt)
{
	 memset(pt,-1,sizeof(pt));
     while(!Q.empty())
          Q.pop();
     Q.push(st);
     pt[st]=0;
     int i;
     while(!Q.empty())
     {
          int d=Q.front();
          Q.pop();
          for(i=head[d];i!=0;i=a[i].next)
          {
               int t=a[i].t;
               if(a[i].f>0&&pt[t]==-1)
               {
                    Q.push(t);
                    pt[t]=pt[d]+1;
               }
          }
     }
     if(pt[tt]>=0)
          return true;
     return false;
}
inline int dfs(int d,int tt,int s)
{
	 if(d==tt)
	      return s;
     int tx=s;
     int i;
     for(i=head[d];i!=0;i=a[i].next)
     {
          int t=a[i].t;
          if(pt[t]==pt[d]+1&&a[i].f>0)
          {
               int xx=dfs(t,tt,min(s,a[i].f));
               a[i].f-=xx;
               if(i%2==0)
                    a[i-1].f+=xx;
               else
                    a[i+1].f+=xx;
               s-=xx;
          }
     }
     return tx-s;
}
inline int dinic(int st,int tt)
{
     int s=0;
     while(bfs(st,tt))
          s+=dfs(st,tt,2100000000);
     return s;
}
int xt[10001];
int s1[10001],s2[10001];
int v[10001];
int belong[10001];
int sx[10001];
int loc[1001][1001];
inline void dfsx(int d,int x)
{
	 v[d]=true;
     belong[d]=x;
     sx[x]++;
     loc[x][sx[x]]=d;
     int i;
     for(i=head[d];i!=0;i=a[i].next)
     {
          int t=a[i].t;
          if(v[t])
               continue;
          if(xt[d]%2==1)
          {
               if(a[i].f==0&&t!=0)
                    dfsx(t,x);
          }
          else
          {
               if(a[i].f==1&&t!=p)
                    dfsx(t,x);
          }
     }
}
int main()
{
     int n;
     scanf("%d",&n);
     int i,j,k;
     int p1=0,p2=0;
     p=n+1;
     int lf=0,ri=0;
     for(i=1;i<=n;i++)
     {
          scanf("%d",&xt[i]);
          if(xt[i]%2==1)
          {
               p1++;
               s1[p1]=i;
               edge++;
               add(0,i,2);
               edge++;
               add(i,0,0);
               lf+=2;
          }
          else
          {
               p2++;
               s2[p2]=i;
               edge++;
               add(i,p,2);
               edge++;
               add(p,i,0);
               ri+=2;
          }
     }
     for(i=1;i<=p1;i++)
     {
          for(j=1;j<=p2;j++)
          {
               int s=xt[s1[i]]+xt[s2[j]];
               if(pd(s))
               {
                    edge++;
                    add(s1[i],s2[j],1);
                    edge++;
                    add(s2[j],s1[i],0);
               }
          }
     }
     if(lf!=ri)
     {
          printf("Impossible\n");
          return 0;
     }
     int all=dinic(0,p);
     if(all!=ri)
     {
          printf("Impossible\n");
          return 0;
     }
     int sum=0;
     for(i=1;i<=n;i++)
     {
          if(!v[i])
          {
          	   sum++;
          	   v[i]=false;
               dfsx(i,sum);
          }
     }
     printf("%d\n",sum);
     for(i=1;i<=sum;i++)
     {
          printf("%d",sx[i]);
          for(j=1;j<=sx[i];j++)
               printf(" %d",loc[i][j]);
          printf("\n");
     }
     return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值