uva 10319 - Manhattan (2SAT)

来源:互联网 发布:java简明教程 pdf下载 编辑:程序博客网 时间:2024/05/20 19:19

Problem H

Manhattan

Input: standard input

Output:  standard output

Time Limit: 1 second

Memory Limit: 32 MB

 

 

You are the mayor of a city with severe traffic problems. To deal with the situation, you have decided to make a new plan for the street grid. As it is impossible to make the streets wider, your approach is to make them one-way (only traffic in one direction is allowed on a street), thus creating a more efficient flow of traffic.

 

The streets in the city form an orthogonal grid - like on Manhattan avenues run in north-south-direction, while streets run in east-west-direction. Your mission is to make all the streets and avenues one-way, i.e. fix the direction in which traffic is allowed, while maintaining a short driving distance between some ordered pairs of locations. More specifically, a route in the city is defined by two street-avenue crossings, the start and goal location. On a one-way street grid, a route has a legal path if it is possible to drive from the start location to the goal location along the path passing streets and avenues in their prescribed direction only. A route does not define a specific path between the two locations - there may be many possible paths for each route. A legal path in a one-way street grid is considered simple if it requires at most one turn, i.e. a maximum of one street and one avenue need to be used for the path.

 

When traveling by car from one location to another, a simple path will be preferred over a non-simple one, since it is faster. However, as each street in the grid is one-way, there may always be routes for which no simple path exists. On your desk lies a list of important routes which you want to have simple paths after the re-design of the street grid.

 

Your task is to write a program that determines if it is possible to fix the directions of the one-way streets and avenues in such a way that each route in the list has at least one simple path.

 

Input

On the first line of the input, there is a single integer n, telling how many city descriptions that follows. Each city description begins with a line containing three integers: the number of streets 0<S<=30 and avenues 0<A<=30 in the street grid, and the number of routes 0<m<=200 that should have at least one simple path. The next m lines define these routes, one on each line. Each route definition consists of four integers, s1a1s2a2, where the start location of the route is at the crossing of street s1and avenue a1, and the goal location is at the crossing of street s2 and avenue a2. Obviously, 0<s1, s2<=S and 0<a1, a2<=A.

 

Output

For each city, your program should output 'Yes' on a single line if it is possible to make the streets and avenues one-way, so that each route has at least one simple path. Otherwise the text 'No' should be printed on a line of its own.

 

Sample Input

3

6 6 2

1 1 6 6

6 6 1 1

7 7 4

1 1 1 6

6 1 6 6

6 6 1 1

4 3 5 1

9 8 6

2 2 4 4

4 5 3 2

3 4 2 2

3 2 4 4

4 5 2 2

2 1 3 4

 

Sample Output

Yes

No

No


(The Decider Contest, Problem Source: Swedish National Programming Contest, arranged by department of Computer Science at Lund Institute of Technology.)


给所有横纵的街道定向,满足它给定的条件。很明显的2SAT问题,不过这道题不同的在于如果a->b不满足,则必须走c->d,即每个条件下涉及了四个变量。所以可以分别连边,即a和c,a和d,b和c,b和d。这样建图就搞定了。

#include<cstdio>#include<map>#include<queue>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#include<list>#include<set>#include<cmath>using namespace std;const int maxn = 100 + 5;const int INF = 1e9;const double eps = 1e-6;typedef unsigned long long ULL;typedef long long LL;typedef pair<int, int> P;#define fi first#define se secondint row, col;struct TwoSAT {  int n;  vector<int> G[maxn*2];  bool mark[maxn*2];  int S[maxn*2], c;  bool dfs(int x) {    if (mark[x^1]) return false;    if (mark[x]) return true;    mark[x] = true;    S[c++] = x;    for (int i = 0; i < G[x].size(); i++)      if (!dfs(G[x][i])) return false;    return true;  }  void init(int n) {    this->n = n;    for (int i = 0; i < n*2; i++) G[i].clear();    memset(mark, 0, sizeof(mark));  }  int Hash(int pos, int kind){    int ret;    if(kind == 1)        ret = (row+pos)*2+1;    else if(kind == 2)        ret = pos*2+1;    else if(kind == 3)        ret = (row+pos)*2;    else if(kind == 4)        ret = pos*2;    return ret;  }  void add_edge(int from, int kind1, int to, int kind2){    int x = Hash(from, kind1);    int y = Hash(to, kind2);    G[x^1].push_back(y);    G[y^1].push_back(x);  }  void Add(int a1, int kinda1, int a2, int kinda2, int b1, int kindb1, int b2, int kindb2){    add_edge(a1, kinda1, b1, kindb1);    add_edge(a1, kinda1, b2, kindb2);    add_edge(a2, kinda2, b1, kindb1);    add_edge(a2, kinda2, b2, kindb2);  }  bool solve() {    for(int i = 0; i < n*2; i += 2){      if(mark[i] && mark[i+1])        return false;      if(!mark[i] && !mark[i+1]) {        c = 0;        if(!dfs(i)) {          while(c > 0) mark[S[--c]] = false;          if(!dfs(i+1)) return false;        }      }    }    return true;  }};TwoSAT solver;int main(){    int t, num;    cin >> t;    while(t--){        cin >> col >> row >> num;        solver.init(col+row+5);        while(num--){            int sx, sy, ex, ey;            cin >> sx >> sy >> ex >> ey;            int dx = ex-sx;            int dy = ey-sy;            if(dx<0 && dy==0){                solver.add_edge(sy, 1, sy, 1);            }            else if(dx<0 && dy>0){                solver.Add(sy, 1, ex, 2, sx, 2, ey, 1);            }            else if(dx==0 && dy>0){                solver.add_edge(sx, 2, sx, 2);            }            else if(dx>0 && dy>0){                solver.Add(sx, 2, ey, 3, sy, 3, ex, 2);            }            else if(dx>0 && dy==0){                solver.add_edge(sy, 3, sy, 3);            }            else if(dx>0 && dy<0){                solver.Add(sx, 4, ey, 3, sy, 3, ex, 4);            }            else if(dx==0 && dy<0){                solver.add_edge(sx, 4, sx, 4);            }            else if(dx<0 && dy<0){                solver.Add(sx, 4, ey, 1, ex, 4, sy, 1);            }        }        bool ans = solver.solve();        if(ans)            cout << "Yes" << endl;        else            cout << "No" << endl;    }    return 0;}


0 0