zoukankan      html  css  js  c++  java
  • 西电10.9校内赛补题

     C.

    http://www.cnblogs.com/elpsycongroo/p/7643771.html

    D.UVa12880

    解题关键:dfs,判断每个人是否愿意被其他人交换,注意保证每个人只能被交换一次。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<iostream>
     7 #define maxn 220000
     8 using namespace std;
     9 typedef long long ll;
    10 struct Edge{
    11     int nxt;
    12     int to;
    13 }e[maxn];
    14 int head[maxn],cnt,pre[maxn];
    15 bool vis[maxn];
    16 void add_edge(int u,int v){//单向
    17     e[cnt].to=v;
    18     e[cnt].nxt=head[u];
    19     head[u]=cnt++;
    20 }
    21 bool dfs(int u){
    22     for(int i=head[u];i!=-1;i=e[i].nxt){
    23         int v=e[i].to;
    24         if(vis[v]) continue;
    25         vis[v]=true;
    26         if(pre[v]==-1||dfs(pre[v])){
    27             pre[v]=u;
    28             return true;
    29         }
    30     }
    31     return false;
    32 }
    33 int main(){
    34     int n,m,a,b;
    35     while(scanf("%d%d",&n,&m)!=EOF){
    36         memset(head, -1, sizeof head);
    37         memset(pre,-1,sizeof pre);
    38         cnt=0;
    39         for(int i=0;i<m;i++){
    40             scanf("%d%d",&a,&b);
    41             add_edge(a,b);
    42         }
    43         for(int i=0;i<n;i++){
    44             memset(vis,0,sizeof vis);
    45             dfs(i);
    46         }
    47         bool flag=false;
    48         for(int i=0;i<n;i++){
    49             if(pre[i]==-1){
    50                 flag=true;
    51                 break;
    52             }
    53         }
    54         if(flag) printf("NO
    ");
    55         else printf("YES
    ");
    56     }
    57     return 0;
    58 }
    View Code

    E.hdu4313

    解题关键:正向的思路是将边从小到大排序,如果去掉某条边,两个特殊点并起来了,则需去掉该边,我们反向考虑,将边从大到小排序,依次向图中加边,如果两个点并起来了,则需去掉该边。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<iostream>
     6 #include<vector>
     7 #include<cmath>
     8 #define maxn 100020
     9 using namespace std;
    10 typedef long long ll;
    11 int par[maxn],n,k;
    12 //bool vis[maxn];
    13 struct edge{
    14     int u;
    15     int v;
    16     int w;
    17 }e[maxn];
    18 bool flag[maxn];
    19 bool cmp(const edge &a,const edge &b){
    20     return a.w>b.w;
    21 }
    22 void init1(){
    23     for(int i=0;i<=n;i++) par[i]=i;
    24 }
    25 
    26 int find1(int x){
    27     if(par[x]==x) return x;
    28     else return par[x]=find1(par[x]);
    29 }
    30 
    31 void unite(int x,int y){
    32     par[x]=y;
    33 }
    34 
    35 int main(){
    36     int t,a;
    37     ios::sync_with_stdio(0);
    38     cin>>t;
    39     while(t--){
    40         memset(flag, 0, sizeof flag);
    41         cin>>n>>k;
    42         init1();
    43         for(int i=0;i<n-1;i++){
    44             cin>>e[i].u>>e[i].v>>e[i].w;
    45         }
    46         sort(e,e+n-1,cmp);
    47         for(int i=0;i<k;i++){
    48             cin>>a;
    49             flag[a]=1;
    50         }
    51         ll ans=0;
    52         for(int i=0;i<n-1;i++){
    53             if(flag[find1(e[i].u)]&&flag[find1(e[i].v)]){
    54                 ans+=e[i].w;
    55             }
    56             else if(flag[find1(e[i].u)]){
    57                 unite(find1(e[i].v),find1(e[i].u));
    58             }else{
    59                 unite(find1(e[i].u), find1(e[i].v));
    60             }
    61         }
    62         cout<<ans<<"
    ";
    63     }
    64     return 0;
    65 }
    View Code

     F.hdu4324

    解题关键:

    求是否存在三元环 
    如果存在环,则一定存在三元环 (scc和拓扑排序均可)
    证明如下: 
    不存在二元环 
    设存在 $n(n>=3)$元环 $p_1->p_2->p_3->…->p_n->p_1$ 
    1) 若存在边 $p_3->p_1$,则存在三元环 $(p_1->p_2->p_3->p_1)$ 
    2) 若不存在 $p_3->p_1$,则必然存在 $p_1->p_3$ 
    那么 $p_1->p_3->…->p_n->p_1$又构成 $n-1$元环 
    递归证明可得,如果存在环,必然存在三元环。

    1、targinSCC

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<algorithm>
     7 using namespace std;
     8 typedef long long ll;
     9 #define MAXN 2010
    10 #define MAXM 4000020
    11 struct edge{
    12     int to,nxt;
    13 }e[MAXM];
    14 //int being[MAXN];
    15 int head[MAXN],st[MAXN],dfn[MAXN],lowest[MAXN],belong[MAXN];
    16 bool inst[MAXN];
    17 int t,n,m,scnt,top,tot;//scnt从1开始
    18 void init(){
    19     memset(head,-1,sizeof head);
    20     memset(dfn,0,sizeof dfn);//记住初始化
    21   //  memset(being, 0, sizeof being);
    22     scnt=top=tot=0;
    23 }
    24 
    25 void add_edge(int u, int v){
    26     e[tot].to=v;
    27     e[tot].nxt=head[u];
    28     head[u]=tot++;
    29 }
    30 
    31 void Tarjan(int u){
    32     dfn[u]=lowest[u]=++tot;
    33     inst[u]=1;
    34     st[top++]=u;
    35     for(int i=head[u];i!=-1;i=e[i].nxt){
    36         int v=e[i].to;
    37         if(!dfn[v]){
    38             Tarjan(v);
    39             lowest[u]=min(lowest[u],lowest[v]);
    40         }
    41         else if(inst[v]){
    42             lowest[u]=min(lowest[u],dfn[v]);//也可用lowest
    43         }
    44     }
    45     if(dfn[u]==lowest[u]){
    46         scnt++;
    47         int t;
    48         do{
    49             t=st[--top];
    50             inst[t]=false;
    51             belong[t]=scnt;
    52         }while(t!=u);
    53     }
    54 }
    55 
    56 void solve(){//缩点
    57     for(int i=1;i<=n;i++)  if(!dfn[i])  Tarjan(i);
    58    /* for(int i=1;i<=n;i++){
    59         being[belong[i]]++;
    60     }
    61     bool flag=false;
    62     for(int i=1;i<=scnt;i++){
    63         if(being[i]>1){
    64             flag=true;
    65             break;
    66         }
    67     }
    68     */
    69     if(scnt!=n) printf("Yes
    ");
    70     //if(flag) printf("Yes
    ");
    71     else printf("No
    ");
    72 }
    73 char ch[2200];
    74 int main(){
    75     scanf("%d",&t);
    76     for(int i=1;i<=t;i++){
    77         init();
    78         printf("Case #%d: ",i);
    79         scanf("%d",&n);
    80         for(int j=1;j<=n;j++){
    81             scanf("%s",ch);
    82             for(int k=0;k<n;k++){
    83                 if(ch[k]=='1') add_edge(j,k+1);
    84             }
    85         }
    86         solve();
    87     }
    88     return 0;
    89 }
    View Code

     2、toposort

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<iostream>
     6 #include<cmath>
     7 #include<vector>
     8 #include<queue>
     9 using namespace std;
    10 typedef long long ll;
    11 const int N=4000200;
    12 priority_queue<int,vector<int>,greater<int> >q;//因为是按字典序的,要注意重边的情况
    13 int deg[2002],seq[2002];
    14 int n,m,u,v,tol,t;
    15 struct Edge{
    16     int nxt;
    17     int to;
    18     int w;
    19 }e[N];
    20 int head[N],cnt;
    21 void add_edge(int u,int v){
    22     e[cnt].to=v;
    23     e[cnt].nxt=head[u];
    24     head[u]=cnt++;
    25 }
    26 bool toposort(){
    27     for(int i=1;i<=n;i++)if(!deg[i])q.push(i);
    28     tol=0;
    29     while(q.size()){
    30         int u=q.top();
    31         q.pop();
    32         seq[tol++]=u;
    33         for(int i=head[u];i!=-1;i=e[i].nxt){
    34             int v=e[i].to;
    35             deg[v]--;
    36             if(!deg[v]) q.push(v);
    37         }
    38     }
    39     if(tol==n) return false;
    40     else return true;
    41 }
    42 char ch[2002];
    43 int main(){
    44     scanf("%d",&t);
    45     for(int i=1;i<=t;i++){
    46         memset(head, -1, sizeof head);
    47         memset(deg, 0, sizeof deg);
    48         cnt=0;
    49         scanf("%d",&n);
    50         for(int j=1;j<=n;j++){
    51             scanf("%s",ch);
    52             for(int k=0;k<n;k++){
    53                 if(ch[k]=='1') add_edge(j,k+1),deg[k+1]++;
    54             }
    55         }
    56         bool flag=toposort();
    57         printf("Case #%d: ",i);
    58         if(flag) printf("Yes
    ");
    59         else printf("No
    ");
    60     }
    61     return 0;
    62 }
    View Code

    G.hdu4318

    解题关键:最短路转化为最长路。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<iostream>
     6 #include<cmath>
     7 #include<queue>
     8 using namespace std;
     9 const int maxn=50002;
    10 const int maxm=2600010;
    11 int head[maxn],tot,n,m;
    12 struct edge{
    13     int to;
    14     double w;
    15     int nxt;
    16 }e[maxm];
    17 void add_edge(int u,int v,double w){
    18     e[tot].w=w;
    19     e[tot].to=v;
    20     e[tot].nxt=head[u];
    21     head[u]=tot++;
    22 }
    23 bool vis[maxn];
    24 queue<int>que;//队列是点的队列
    25 double d[maxn];
    26 void spfa(int s){
    27     for(int i=0;i<=n;i++) d[i]=0.0;
    28     memset(vis,0,sizeof vis);
    29     while (!que.empty()) que.pop();
    30     que.push(s);
    31     vis[s]=true;
    32     d[s]=1.0;
    33     while (!que.empty()){
    34         int u=que.front();
    35         que.pop();
    36         vis[u]=false;
    37         for (int i=head[u];i!=-1;i=e[i].nxt){
    38             int v=e[i].to;
    39             double w=e[i].w;
    40             if (d[v]<d[u]*w){
    41                 d[v]=d[u]*w;
    42                 if (!vis[v]){
    43                     vis[v]=true;
    44                     que.push(v);//hash一下,可判断是否存在负环
    45                 }
    46             }
    47         }
    48     }
    49 }
    50 int main(){
    51     int a,b,k,td;
    52     //double c;
    53     while(scanf("%d",&n)!=EOF){
    54         memset(head, -1, sizeof head);
    55         tot=0;
    56         for(int i=0;i<n;i++){
    57             scanf("%d",&k);
    58             for(int j=0;j<k;j++){
    59                 scanf("%d%d",&b,&td);
    60                 add_edge(i+1,b,1-td*0.01);
    61             }
    62         }
    63         scanf("%d%d%d",&a,&b,&td);
    64         spfa(a);
    65         if(d[b]==0){
    66             printf("IMPOSSIBLE!
    ");
    67         }else{
    68             printf("%.2f
    ",td-td*d[b]);
    69         }
    70     }
    71     return 0;
    72 }
    View Code

    H.hdu4302

    解题关键:优先队列分别维护左右距离x最近的点,然后模拟即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 priority_queue<int>q1;
     5 priority_queue<int,vector<int>,greater<int> >q2;
     6 int main(){
     7     int t,l,n,a,b,now,x,m,ans;
     8     scanf("%d",&t);
     9     for(int ca=1;ca<=t;ca++){
    10         x=0;
    11         scanf("%d%d",&n,&m);
    12         while(!q1.empty()) q1.pop();
    13         while(!q2.empty()) q2.pop();
    14         ans=0;
    15         for(int i=0;i<m;i++){
    16             scanf("%d",&a);
    17             if(a==1){
    18                 if(!q1.empty()&&!q2.empty()){
    19                     int t1=x-q1.top();
    20                     int t2=q2.top()-x;
    21                     if(t1<t2){
    22                         x=q1.top();
    23                         now=-1;
    24                         ans+=t1;
    25                         q1.pop();
    26                     }
    27                     else if(t1>t2){
    28                         x=q2.top();
    29                         now=1;
    30                         q2.pop();
    31                         ans+=t2;
    32                     }
    33                     else if(now==1){
    34                         x=q2.top();
    35                         now=1;
    36                         q2.pop();
    37                         ans+=t2;
    38                     }else{
    39                         x=q1.top();
    40                         now=-1;
    41                         q1.pop();
    42                         ans+=t1;
    43                     }
    44                 }
    45                 else if(!q1.empty()){
    46                     int t1=x-q1.top();
    47                     now=-1;
    48                     x=q1.top();
    49                     ans+=t1;
    50                     q1.pop();
    51                 }
    52                 else if(!q2.empty()){
    53                     int t2=q2.top()-x;
    54                     now=1;
    55                     x=q2.top();
    56                     q2.pop();
    57                     ans+=t2;
    58                 }
    59             }else{
    60                 scanf("%d",&b);
    61                 if(b>x){
    62                     q2.push(b);
    63                 }else{
    64                     q1.push(b);
    65                 }
    66             }
    67         }
    68         printf("Case %d: %d
    ",ca,ans);
    69     }
    70 } 
    View Code

    I.hdu4308

    解题关键:bfs简单裸题,考验手速和细节。

     1 #include<bits/stdc++.h>
     2 #define inf 0x3f3f3f3f
     3 using namespace std;
     4 typedef long long ll;
     5 char arr[5002][5002];
     6 int r,c,cost,sx,sy,tx,ty;
     7 struct node{
     8     int x,y;
     9 };
    10 int d[5002][5002];
    11 const int dx[4]={1,0,-1,0};
    12 const int dy[4]={0,1,0,-1};
    13 node q1[5002];int rear;
    14 int bfs(node st){
    15     for(int i=0;i<r;i++) for(int j=0;j<c;j++) d[i][j]=inf;
    16     queue<node>q;
    17     q.push(st);
    18     d[st.x][st.y]=0;
    19     while(q.size()){
    20         node p=q.front();
    21         q.pop();
    22         //if(p.x==tx&&p.y==ty) return d[p.x][p.y];
    23         for(int i=0;i<4;i++){
    24             int nx=p.x+dx[i],ny=p.y+dy[i];
    25             if(nx<0||nx>=r||ny<0||ny>=c||arr[nx][ny]=='#'||d[nx][ny]!=inf) continue;
    26             if(arr[nx][ny]=='*'){
    27                 q.push((node){nx,ny});
    28                 d[nx][ny]=d[p.x][p.y]+1;
    29             }else if(arr[nx][ny]=='P'){
    30                 d[nx][ny]=d[p.x][p.y];
    31                 for(int i=0;i<rear;i++){
    32                     int tmpx=q1[i].x,tmpy=q1[i].y;
    33                     d[tmpx][tmpy]=d[nx][ny];
    34                     q.push((node){tmpx,tmpy});
    35                 }
    36             }else if(arr[nx][ny]=='C'){
    37                 d[nx][ny]=d[p.x][p.y];
    38                 return d[nx][ny];
    39             }
    40         }
    41     }
    42     return -1;
    43 }
    44 int main(){
    45     while(scanf("%d%d%d",&r,&c,&cost)!=EOF){
    46         rear=0;
    47         for(int i=0;i<r;i++) scanf("%s",arr+i);
    48         for(int i=0;i<r;i++) for(int j=0;j<c;j++){
    49              if(arr[i][j]=='Y') sx=i,sy=j;
    50             if(arr[i][j]=='C') tx=i,ty=j; 
    51             if(arr[i][j]=='P'){
    52                 q1[rear++]=(node){i,j};
    53             }
    54         }
    55         int ans=bfs((node){sx,sy});
    56         if(ans==-1) printf("Damn teoy!
    ");
    57         else printf("%d
    ",ans*cost);
    58     }
    59     return 0;
    60 } 
    View Code

    J.UVa1521

    解题关键:贪心,会得出猜的数是1时需要的步数最大,然后就是将n以内的质数全部筛出,转化为质数分组的问题,然后双指针解决即可。

    每次询问,相当于确定每个质数P是否出现。考虑到最坏情况,一定是问什么都回答1,否则的话就相当于把$n$缩小成了$frac{n}{p}$。

    问题就转换成了将1~n中间的质数分成K组,每组内的质数之积不大于$n$,求最小的$k$。

    对于不小于$sqrt{n}$的质数来说,他一定只能和小于$sqrt{n}$的质数来配对,这样答案至少为不小于$sqrt{n}$的质数个数。

    而小于$sqrt{n}$的质数的个数一定比不小于$sqrt{n}$的质数的个数小很多,并且一定可以找到一个质数来配对。

    所以问题的答案可以通过贪心来求,递减枚举每一个不小于质数,判断当前最小质数是否可以合并。

    1、考虑乘法,小的因子每增大1,大的因子势必会减小很多,利用这个性质,可以得到,每个小的因子只能和一个大的因子合并。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int MAXN=30001;
     5 int prime[MAXN];//保存素数
     6 bool vis[MAXN];//初始化
     7 int LSsieve(int n){
     8     int cnt=0;
     9     memset(vis,0,sizeof vis);
    10     for(int i=2;i<n;i++){
    11         if(!vis[i]) prime[cnt++]=i;
    12         for(int j=0;j<cnt&&i*prime[j]<n;j++){
    13             vis[i*prime[j]]=1;
    14             if(i%prime[j]==0)   break;
    15         }
    16     }
    17     return cnt;//返回小于n的素数的个数 
    18 }
    19 
    20 
    21 int main(){
    22     int n;
    23     int cnt=LSsieve(10001);
    24     while(scanf("%d",&n)!=EOF){
    25         int i=0,j=cnt-1,ans=0;
    26         while(prime[j]>n) j--;
    27         while(i<=j){
    28             ans++;
    29             if(prime[i]*prime[j]<=n) i++,j--;
    30             else j--; 
    31         }
    32         printf("%d
    ",ans);
    33     }
    34 
    35     return 0;
    36 } 
    View Code

     2、暴力分组。先取最大,然后用小的填充。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<iostream>
     6 #include<cmath>
     7 using namespace std;
     8 typedef long long ll;
     9 const int MAXN=30001;
    10 int prime[MAXN];//保存素数
    11 bool vis[MAXN];//初始化
    12 int LSsieve(int n){
    13     int cnt=0;
    14     memset(vis,0,sizeof vis);
    15     for(int i=2;i<n;i++){
    16         if(!vis[i]) prime[cnt++]=i;
    17         for(int j=0;j<cnt&&i*prime[j]<n;j++){
    18             vis[i*prime[j]]=1;
    19             if(i%prime[j]==0)  break;
    20         }
    21     }
    22     return cnt;//返回小于n的素数的个数
    23 }
    24 
    25 
    26 int main(){
    27     int n;
    28     int cnt=LSsieve(10001);
    29     while(scanf("%d",&n)!=EOF){
    30         int i=0,j=cnt-1,ans=0,now;
    31         while(prime[j]>n) j--;
    32         while(i<=j){
    33             now=prime[j];
    34             while(prime[i]*now<=n) now*=prime[i],i++;
    35             j--;
    36             ans++;
    37         }
    38         printf("%d
    ",ans);
    39     }
    40     return 0;
    41 }
    View Code
  • 相关阅读:
    alpine python3中使用mysql报错ModuleNotFoundError: No module named 'MySQLdb'
    Galera集群部署
    Kibana did not load properly.Check the server output for more information。
    zabbix-server迁移
    traefik使用etcd存储配置
    Rancher2.4搭建单机版rabbitmq
    ngx_http_upstream_module模块说明
    【说明】
    运维日常集合(个人向 坚持更新)
    Linux监控-历史细项数据回溯
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7648697.html
Copyright © 2011-2022 走看看