zoukankan      html  css  js  c++  java
  • Codeforces Round #383 (Div. 1)

    A:

    题目大意:给出一个有向图(n<=100),每个点的出度都为1,求最小的t,使得任意两点x,y,如果x走t步后能到y,那么y走t步后到x。

    题解:

    首先每个点应该都在一个环上,否则无解。

    对于大小为k的奇环上的点,满足要求的最小的t是k.

    对于大小为k的偶环上的点,满足要求的最小的t是k/2.

    对于每个环求最小公倍数即可。  数据范围很小,直接暴力求环就可以了。

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <map>
     8 #include <cstdlib>
     9 #include <set>
    10 using namespace std;
    11 
    12 #define X first
    13 #define Y second
    14 #define Mod 1000000007
    15 #define N 110
    16 typedef long long ll;
    17 typedef pair<int,int> pii;
    18 
    19 int n;
    20 int a[N];
    21 bool vis[N];
    22 
    23 ll gcd(ll x,ll y)
    24 {
    25     ll tmp;
    26     while (y)
    27     {
    28         tmp=x%y;
    29         x=y;y=tmp;
    30     }
    31     return x;
    32 }
    33 
    34 ll lcm(ll x,ll y)
    35 {
    36     return x/gcd(x,y)*y;
    37 }
    38 
    39 int main()
    40 {
    41     //freopen("in.in","r",stdin);
    42     //freopen("out.out","w",stdout);
    43     
    44     scanf("%d",&n);
    45     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    46     ll ans=1;
    47     for (int i=1;i<=n;i++)
    48     {
    49         int t=i,c=0;
    50         memset(vis,0,sizeof(vis));
    51         do
    52         {
    53             vis[t]=true;
    54             c++,t=a[t];
    55         }while(!vis[t]);
    56         if (t==i)
    57         {
    58             if (!(c&1)) c>>=1;
    59             ans=lcm(ans,c);
    60         }
    61         else 
    62         {
    63             printf("-1
    ");
    64             return 0;
    65         }
    66     }
    67     printf("%d
    ",ans);
    68     return 0;
    69 }
    View Code

    B:

    题目大意: 你要从n个客人中邀请一些人来参加派对, 每个客人有一个w和b。要求在邀请的客人的w之和不能超过W的情况下,使得客人的b的和最大。 n,W<=1000

    有一些客人是朋友关系,且满足传递性,对于一些朋友,要么全部邀请,要么最多邀请其中的一个。

    题解: 

    考虑DP。 首先用并查集搞出朋友关系的集合,dp[i][j]表示考虑前i个集合,w的和为j的最优解。

    转移的时候 要么把整个第i个集合取过来,要么枚举其中的一个元素取过来。

    考虑复杂度: 对于第k个人,假设他在第i个集合,那么他在dp[i][0.....W]的时候都用来转移了一次。

    所以复杂度是O(nW).

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <map>
     8 #include <cstdlib>
     9 #include <set>
    10 using namespace std;
    11 
    12 #define X first
    13 #define Y second
    14 #define Mod 1000000007
    15 #define N 1010
    16 #define M 10000010
    17 typedef long long ll;
    18 typedef pair<int,int> pii;
    19 
    20 
    21 int n,m,w;
    22 int a[N],b[N],father[N],id[N];
    23 int s1[N],s2[N];
    24 int dp[N][N];
    25 
    26 vector<int> g[N];
    27 
    28 int Find(int x)
    29 {
    30     if (father[x]==x) return x;
    31     father[x]=Find(father[x]);
    32     return father[x];
    33 }
    34 
    35 void Merge(int x,int y)
    36 {
    37     x=Find(x),y=Find(y);
    38     if (x==y) return ;
    39     father[x]=y;
    40 }
    41 
    42 int main()
    43 {
    44     //freopen("in.in","r",stdin);
    45     //freopen("out.out","w",stdout);
    46     
    47     scanf("%d%d%d",&n,&m,&w);
    48     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    49     for (int i=1;i<=n;i++) scanf("%d",&b[i]),father[i]=i;
    50     int x,y;
    51     for (int i=1;i<=m;i++)
    52     {
    53         scanf("%d%d",&x,&y);
    54         Merge(x,y);
    55     }
    56     int t=0;
    57     for (int i=1;i<=n;i++) if (Find(i)==i) id[i]=++t;
    58      for (int i=1;i<=n;i++) 
    59     {
    60          int x=id[Find(i)];
    61          g[x].push_back(i);
    62          s1[x]+=a[i];
    63          s2[x]+=b[i];
    64     }
    65     
    66     int ans=0; 
    67     for (int i=1;i<=t;i++)
    68     {
    69         for (int j=0;j<=w;j++)
    70         {
    71             dp[i][j]=dp[i-1][j];
    72             if (j>=s1[i]) dp[i][j]=max(dp[i][j],dp[i-1][j-s1[i]]+s2[i]);
    73             for (int k=0;k<g[i].size();k++)
    74             {
    75                 if (j>=a[g[i][k]]) dp[i][j]=max(dp[i][j],dp[i-1][j-a[g[i][k]]]+b[g[i][k]]);
    76             }
    77             if (i==t) ans=max(ans,dp[i][j]);
    78         }
    79     }
    80     printf("%d
    ",ans);
    81     
    82     return 0;
    83 }
    View Code

    C:

    题目大意:n对男女(2n个人)围成一圈,要给他们黑白染色,要求任意三个相邻的人颜色不能完全一样。  第i对情侣分别是ai和bi,他们的颜色要不一样。 n<=100000.

    题解:

    比赛的时候没有想出来...下面是官方题解:

    首先给ai和bi连边,然后给2*i-1和2*i 连边,可以证明这个图是二分图,做一次染色就好啦。

    证明:

    记给ai和bi连的边为A类边,2*i-1和2*i 连的边为B类边。

    由于一个人不可能和多个人是男女朋友关系,所以对于每个点有且只有1条A类边和它相连,同时有且只有1条B类边。

    考虑任意一个环。 对于环上的边,只能是AB类边交替,否则就会有2条A类边或者2条B类边和同一个点相连。

    因此环不可能是奇环。 故这个图是二分图。

    代码:

     1  #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <map>
     8 #include <cstdlib>
     9 #include <set>
    10 #include <queue>
    11 using namespace std;
    12 
    13 #define X first
    14 #define Y second
    15 #define Mod 1000000007
    16 #define N 200110
    17 #define M 200110
    18 
    19 typedef long long ll;
    20 typedef pair<int,int> pii;
    21 
    22 const ll INF=4e18;
    23 
    24 int n;
    25 vector<int> g[N];
    26 int color[N],a[N],b[N];
    27 
    28 bool Dfs(int x,int c)
    29 {
    30     color[x]=c;
    31     for (int i=0;i<g[x].size();i++)
    32     {
    33         int y=g[x][i];
    34         if (!color[y] && !Dfs(y,3-c)) return false; 
    35         else if (color[y]==color[x]) return false;
    36     }
    37     return true;
    38 }
    39 
    40 int main()
    41 {
    42     //freopen("in.in","r",stdin);
    43     //freopen("out.out","w",stdout);
    44 
    45     scanf("%d",&n);
    46     for (int i=1;i<=n;i++)
    47     {
    48         int x,y;
    49         scanf("%d%d",&x,&y);
    50         a[i]=x,b[i]=y;
    51         g[x].push_back(y);
    52         g[y].push_back(x);
    53     }
    54     for (int i=1;i<=n;i++) g[2*i-1].push_back(2*i),g[2*i].push_back(2*i-1);
    55     for (int i=1;i<=2*n;i++) if (!color[i]) Dfs(i,1);
    56     for (int i=1;i<=n;i++) printf("%d %d
    ",color[a[i]],color[b[i]]);
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    Nodejs下载和第一个Nodejs示例
    永久关闭Win10工具栏的TaskbarSearch控件
    对称加密,非对称加密,散列算法,签名算法
    【转】TTL和RS232之间的详细对比
    zlg核心板linux系统中查看系统内存等使用信息
    Power BI后台自动刷新数据报错 The operation was throttled by Power BI Premium because there were too many datasets being processed concurrently.
    剪切板和上传文件内容获取
    CSS, LESS, SCSS, SASS总结
    文字程序
    electron 打包“ERR_ELECTRON_BUILDER_CANNOT_EXECUTE”
  • 原文地址:https://www.cnblogs.com/vb4896/p/6144421.html
Copyright © 2011-2022 走看看