zoukankan      html  css  js  c++  java
  • HDU 3472 HS BDC

    题意:有个人有一种记单词方法,如果一个单词的最后一个字母和另外一个单词的首字母相同,他就同时可以记住,现在他想按照这样的规则把n个单词串起来(就是一个单词的最后一个字母和另外一个单词的首字母相同),有些单词的回文串也是有意义的,因此他既可以正着记,也可以倒着记,现在问他能不能调整那些回文串有意义的单词的正序逆序把这n个单词串起来。

    混合图的欧拉路径,不是欧拉回路。如果是混合图的欧拉回路问题,在《网络流建模汇总》这篇论文里已经有了具体的方案了。这里需要做的处理就是,如果存在合法路径,而这个路径不构成回路的话,那么我们可以人为的找出起点和终点(就是度数为奇数的点,且只有两个,根据入度出度谁大谁小可以确定谁是起点谁是终点),然后从终点到起点去连一条容量为1的边,如此一来便构造出了一个的回路。再去按混合图欧拉回路的建图方法去判断是否存在欧拉回路就可以了。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define INF 1<<30
      6 #define maxn 30
      7 #define maxm 10000
      8 using namespace std;
      9 
     10 int v[maxm],next[maxm],w[maxm];
     11 int first[maxn],d[maxn],work[maxn],q[maxn];
     12 int e,S,T;
     13 int in[30],out[30],fa[30],used[30];
     14 
     15 void init(){
     16     e = 0;
     17     memset(first,-1,sizeof(first));
     18 }
     19 
     20 void add_edge(int a,int b,int c){
     21     //printf("add:%d to %d,cap = %d
    ",a,b,c);
     22     v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++;
     23     v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++;
     24 }
     25 
     26 int bfs(){
     27     int rear = 0;
     28     memset(d,-1,sizeof(d));
     29     d[S] = 0;q[rear++] = S;
     30     for(int i = 0;i < rear;i++){
     31         for(int j = first[q[i]];j != -1;j = next[j])
     32             if(w[j] && d[v[j]] == -1){
     33                 d[v[j]] = d[q[i]] + 1;
     34                 q[rear++] = v[j];
     35                 if(v[j] == T)   return 1;
     36             }
     37     }
     38     return 0;
     39 }
     40 
     41 int dfs(int cur,int a){
     42     if(cur == T)    return a;
     43     for(int &i = work[cur];i != -1;i = next[i]){
     44         if(w[i] && d[v[i]] == d[cur] + 1)
     45             if(int t = dfs(v[i],min(a,w[i]))){
     46                 w[i] -= t;w[i^1] += t;
     47                 return t;
     48             }
     49     }
     50     return 0;
     51 }
     52 
     53 int dinic(){
     54     int ans = 0;
     55     while(bfs()){
     56         memcpy(work,first,sizeof(first));
     57         while(int t = dfs(S,INF))   ans += t;
     58     }
     59     return ans;
     60 }
     61 
     62 int find(int x){
     63     return x == fa[x] ? x : fa[x] = find(fa[x]);
     64 }
     65 
     66 int main()
     67 {
     68     int nkase,n;
     69     scanf("%d",&nkase);
     70     for(int kase = 1;kase <= nkase;kase++){
     71         S = 26,T = 27;
     72         memset(in,0,sizeof(in));
     73         memset(out,0,sizeof(out));
     74         memset(used,0,sizeof(used));
     75         for(int i = 0;i < 26;i++)
     76             fa[i] = i;
     77         init();
     78         scanf("%d",&n);
     79         char str[30];
     80         int tmp;
     81         for(int i = 0;i < n;i++){
     82             scanf("%s%d",str,&tmp);
     83             int a = str[0]-'a',b = str[strlen(str)-1]-'a';
     84             out[a]++,in[b]++;
     85             used[a] = 1,used[b] = 1;
     86             if(tmp == 1)    add_edge(a,b,1);
     87             int x = find(a),y = find(b);
     88             if(x != y)  fa[x] = y;
     89         }
     90         bool flag = 1;
     91         for(int i = 0;i < 26;i++)   if(used[i] && flag)
     92             for(int j = 0;j < 26;j++)   if(used[j] && flag)
     93                 if(find(i) != find(j)){
     94                     flag = false;
     95                     break;
     96                 }
     97         int start = -1,end = -1,cnt = 0,sum = 0;
     98         for(int i = 0;i < 26;i++){
     99             //printf("in[%d] = %d,out[%d] = %d
    ",i,in[i],i,out[i]);
    100             int x = out[i]-in[i];
    101             if(x > 0){
    102                 add_edge(S,i,x/2);
    103                 sum += x/2;
    104                 if(x % 2 == 1){
    105                     cnt++;
    106                     start = i;
    107                 }
    108             }
    109             if(x < 0){
    110                 add_edge(i,T,-x/2);
    111                 if(x % 2 == -1){
    112                     cnt++;
    113                     end = i;
    114                 }
    115             }
    116         }
    117         //printf("start = %d,end = %d,sum = %d
    ",start,end,sum);
    118         if(cnt == 2 || cnt == 0){
    119             if(start != -1 && end != -1)
    120                 add_edge(end,start,1);
    121         }
    122         else    flag = false;
    123         if(flag && dinic() == sum) printf("Case %d: Well done!
    ",kase);
    124         else    printf("Case %d: Poor boy!
    ",kase);
    125     }
    126     return 0;
    127 }
    View Code
  • 相关阅读:
    THINKPHP_(4)_TP模型中with、withJoin和多层关联的深入分析
    THINKPHP_(3)_TP6中实现多层关联,第一个表关联第二个表查询出的数据,再关联第三个表
    THINKPHP_(2)_TP模型的多表关联查询和多表字段的关键字搜索。
    THINKPHP_(1)_修改TP源码,支持对中文字符串按拼音进行排序。
    automapper 源中有多个属性类映射到同一个 目标中
    关于简单的 FluentValidation 验证
    关于SkyApm测试部署。
    linq2db.EntityFrameworkCore 介绍
    关于在CentOS上,绘图丢失部分中文字的问题
    NHibernate入门
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3395355.html
Copyright © 2011-2022 走看看