• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
dwtfukgv
博客园    首页    新随笔    联系   管理    订阅  订阅
UVa 1572 Self-Assembly (构造+拓扑排序。。。。。)

题意:给定n个带标号的正方形,标号要么是一个大写字母加一个+或-,要么是00,

当且仅当大写字母相同并且符号相反时可以连接,问你给定的能不能拼成一个无限大的的东西。

析:说实话,真心没有看出来是拓扑排序,后来知道是,可是还是不会写。

既然要拼成无限大,那么只要拼的时候拼出一个环来,又由于每个是无限多的,那么可以一直重复,

就能拼起来无限大的东西,把每个正方形看成一条边,那么不就是一个拓扑排序,看看能不能找到一个环么,

如果能找到,那么就可以,找不到,就不可以。注意的是正方形可以从四面都拼,所以要注意考虑全了,

刚开始,忘了,只考虑了两端,WA。把每个边都标记一下就好,相当于构造出一个图来。

代码如下:

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>

using namespace std;
const int maxn = 55;
int G[maxn][maxn], c[maxn];
char s[10];

int getid(char a, char b) {  return (a - 'A')* 2 + ('+' == b ? 1 : 0);  }

void solve(char a1, char a2, char b1, char b2){
    if('0' == a1 || '0' == b1)  return ;
    int u = getid(a1, a2) ^ 1;
    int v = getid(b1, b2);
    G[u][v] = 1;//构造边
    G[v^1][u^1] = 1;//构造反向边
}

bool dfs(int u){
    c[u] = -1;//作标记,正在访问
    for(int v = 0; v < 52; ++v)  if(G[u][v]){
        if(c[v] < 0)  return false;//存在有向环
        else if(!c[v] && !dfs(v))  return false;
    }
    c[u] = 1;
    return true;
}

bool toposort(){
    memset(c, 0, sizeof(c));
    for(int i = 0; i < 52; ++i)
        if(!dfs(i)) return true;
    return false;
}

int main(){
    int n;
    while(scanf("%d", &n) == 1){
        memset(G, 0, sizeof(G));
        for(int i = 0; i < n; ++i){
            scanf("%s", s);
            solve(s[0], s[1], s[2], s[3]);//考虑全了
            solve(s[4], s[5], s[6], s[7]);
            solve(s[0], s[1], s[4], s[5]);
            solve(s[0], s[1], s[6], s[7]);
            solve(s[2], s[3], s[4], s[5]);
            solve(s[2], s[3], s[6], s[7]);
        }
        if(toposort())  puts("unbounded");
        else puts("bounded");
    }
    return 0;
}

 

posted on 2016-06-13 14:02  dwtfukgv  阅读(413)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3