@ivorysi
2018-01-02T08:26:08.000000Z
字数 23410
阅读 764
笔记
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 2364 Accepted: 1393
The N (2 <= N <= 10,000) cows are so excited: it's prom night! They are dressed in their finest gowns, complete with corsages and new shoes. They know that tonight they will each try to perform the Round Dance.
Only cows can perform the Round Dance which requires a set of ropes and a circular stock tank. To begin, the cows line up around a circular stock tank and number themselves in clockwise order consecutively from 1..N. Each cow faces the tank so she can see the other dancers.
They then acquire a total of M (2 <= M <= 50,000) ropes all of which are distributed to the cows who hold them in their hooves. Each cow hopes to be given one or more ropes to hold in both her left and right hooves; some cows might be disappointed.
For the Round Dance to succeed for any given cow (say, Bessie), the ropes that she holds must be configured just right. To know if Bessie's dance is successful, one must examine the set of cows holding the other ends of her ropes (if she has any), along with the cows holding the other ends of any ropes they hold, etc. When Bessie dances clockwise around the tank, she must instantly pull all the other cows in her group around clockwise, too. Likewise,
if she dances the other way, she must instantly pull the entire group counterclockwise (anti-clockwise in British English).
Of course, if the ropes are not properly distributed then a set of cows might not form a proper dance group and thus can not succeed at the Round Dance. One way this happens is when only one rope connects two cows. One cow could pull the other in one direction, but could not pull the other direction (since pushing ropes is well-known to be fruitless). Note that the cows must Dance in lock-step: a dangling cow (perhaps with just one rope) that is eventually pulled along disqualifies a group from properly performing the Round Dance since she is not immediately pulled into lockstep with the rest.
Given the ropes and their distribution to cows, how many groups of cows can properly perform the Round Dance? Note that a set of ropes and cows might wrap many times around the stock tank.
Line 1: Two space-separated integers: N and M
Lines 2..M+1: Each line contains two space-separated integers A and B that describe a rope from cow A to cow B in the clockwise direction.
Line 1: A single line with a single integer that is the number of groups successfully dancing the Round Dance.
5 4
2 4
3 5
1 2
4 1
1
Explanation of the sample:
ASCII art for Round Dancing is challenging. Nevertheless, here is a representation of the cows around the stock tank:
_1___
/**** \
5 /****** 2
/ /**TANK**|
\ \********/
\ \******/ 3
\ 4____/ /
\_______/
Cows 1, 2, and 4 are properly connected and form a complete Round Dance group. Cows 3 and 5 don't have the second rope they'd need to be able to pull both ways, thus they can not properly perform the Round Dance.
因为强连通分量(两个以上)至少有一个环,所以搜有一个点以上的强连通分量就好了
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 100005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
struct node {
int to,next;
}edge[MAXN*5];
int head[MAXN],sumedge;
int n,m;
int dfn[MAXN],low[MAXN],instack[MAXN],inx,tot;
stack<int> st;
void tarjan(int u) {
dfn[u]=low[u]=++inx;
st.push(u);
instack[u]=1;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(!dfn[v]) {
tarjan(v);
low[u]=min(low[v],low[u]);
}
else if(instack[v]==1) {
low[u]=min(dfn[v],low[u]);
}
}
if(low[u]==dfn[u]) {
++tot;
int cnt=0;
while(1) {
int x=st.top();st.pop();
++cnt;
instack[x]=2;
if(x==u) break;
}
if(cnt==1) --tot;
}
}
void add(int u,int v) {
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
void solve() {
n=read();
m=read();
int u,v;
siji(i,1,m) {
u=read();
v=read();
add(u,v);
}
siji(i,1,n) {
if(!dfn[i]) tarjan(i);
}
printf("%d\n",tot);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B is in the distribution list of school A, then A does not necessarily appear in the list of school B
You are to write a program that computes the minimal number of schools that must receive a copy of the new software in order for the software to reach all schools in the network according to the agreement (Subtask A). As a further task, we want to ensure that by sending the copy of new software to an arbitrary school, this software will reach all schools in the network. To achieve this goal we may have to extend the lists of receivers by new members. Compute the minimal number of extensions that have to be made so that whatever school we send the new software to, it will reach all other schools (Subtask B). One extension means introducing one new member into the list of receivers of one school.
The first line contains an integer N: the number of schools in the network (2 <= N <= 100). The schools are identified by the first N positive integers. Each of the next N lines describes a list of receivers. The line i+1 contains the identifiers of the receivers of school i. Each list ends with a 0. An empty list contains a 0 alone in the line.
Your program should write two lines to the standard output. The first line should contain one positive integer: the solution of subtask A. The second line should contain the solution of subtask B.
5
2 4 3 0
4 5 0
0
0
1 0
1
2
IOI 1996
子任务A比较简单,就是tarjan缩点后入度为0的点
B的话是入度为0和出度为0的点取个max
因为每个出度向某一个走不到入度连一条边(如果每一个入度都能走到就任意连),然后多余的入度都连到某个出度上即可
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 100005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
struct node {
int to,next;
}edge[MAXN*5];
int head[MAXN],sumedge;
int n,m;
int dfn[MAXN],low[MAXN],instack[MAXN],inx,tot,col[MAXN],ind[MAXN],outd[MAXN];
stack<int> st;
void tarjan(int u) {
dfn[u]=low[u]=++inx;
st.push(u);
instack[u]=1;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(!dfn[v]) {
tarjan(v);
low[u]=min(low[v],low[u]);
}
else if(instack[v]==1) {
low[u]=min(dfn[v],low[u]);
}
}
if(low[u]==dfn[u]) {
++tot;
while(1) {
int x=st.top();st.pop();
col[x]=tot;
instack[x]=2;
if(x==u) break;
}
}
}
void add(int u,int v) {
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
void solve() {
n=read();
int u;
siji(i,1,n) {
u=read();
while(u!=0) {
add(i,u);
u=read();
}
}
siji(i,1,n) {
if(!dfn[i]) tarjan(i);
}
siji(i,1,n) {
for(int j=head[i];j;j=edge[j].next) {
int v=edge[j].to;
if(col[v]!=col[i]) {
ind[col[v]]++;
outd[col[i]]++;
}
}
}
if(tot==1) {
puts("1");puts("0");
return;
}
int ans1=0,ans2=0;
siji(i,1,tot) {
if(ind[i]==0) ans1++;
if(outd[i]==0) ans2++;
}
ans2=max(ans1,ans2);
printf("%d\n%d\n",ans1,ans2);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
Consider the two networks shown below. Assuming that data moves around these networks only between directly connected nodes on a peer-to-peer basis, a failure of a single node, 3, in the network on the left would prevent some of the still available nodes from communicating with each other. Nodes 1 and 2 could still communicate with each other as could nodes 4 and 5, but communication between any other pairs of nodes would no longer be possible.
Node 3 is therefore a Single Point of Failure (SPF) for this network. Strictly, an SPF will be defined as any node that, if unavailable, would prevent at least one pair of available nodes from being able to communicate on what was previously a fully connected network. Note that the network on the right has no such node; there is no SPF in the network. At least two machines must fail before there are any pairs of available nodes which cannot communicate.
The input will contain the description of several networks. A network description will consist of pairs of integers, one pair per line, that identify connected nodes. Ordering of the pairs is irrelevant; 1 2 and 2 1 specify the same connection. All node numbers will range from 1 to 1000. A line containing a single zero ends the list of connected nodes. An empty network description flags the end of the input. Blank lines in the input file should be ignored.
For each network in the input, you will output its number in the file, followed by a list of any SPF nodes that exist.
The first network in the file should be identified as "Network #1", the second as "Network #2", etc. For each SPF node, output a line, formatted as shown in the examples below, that identifies the node and the number of fully connected subnets that remain when that node fails. If the network has no SPF nodes, simply output the text "No SPF nodes" instead of a list of SPF nodes.
1 2
5 4
3 1
3 2
3 4
3 5
0
1 2
2 3
3 4
4 5
5 1
0
1 2
2 3
3 4
4 6
6 3
2 5
5 1
0
0
Network #1
SPF node 3 leaves 2 subnets
Network #2
No SPF nodes
Network #3
SPF node 2 leaves 2 subnets
SPF node 3 leaves 2 subnets
这道题在求割点的时候一并求了它把图分成几个块就行
就是low[v]>=dfn[u]出现的次数
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 100005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
struct node {
int to,next;
}edge[MAXN*5];
int head[MAXN],sumedge;
int n,m;
int dfn[MAXN],low[MAXN],cnt[MAXN],inx;
bool is_AP[MAXN];
void tarjan(int u,int fa) {
dfn[u]=low[u]=++inx;
int son=0;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(!dfn[v]) {
tarjan(v,u);
++son;
low[u]=min(low[u],low[v]);
if(fa!=0 && low[v]>=dfn[u]) {
is_AP[u]=1;
cnt[u]++;
}
}
else if(v!=fa){
low[u]=min(dfn[v],low[u]);
}
}
if(fa!=0 && is_AP[u]) ++cnt[u];
if(fa==0 && son>1) is_AP[u]=1,cnt[u]=son;
}
void add(int u,int v) {
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
void addtwo(int u,int v) {
add(u,v);add(v,u);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
int u,v,n;
int t=0;
while(1) {
++t;
n=0;
memset(head,0,sizeof(head));
sumedge=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(is_AP,0,sizeof(is_AP));
memset(cnt,0,sizeof(cnt));
inx=0;
scanf("%d",&u);
if(u==0) break;
while(u!=0) {
scanf("%d",&v);
n=max(n,u);
n=max(n,v);
addtwo(u,v);
scanf("%d",&u);
}
siji(i,1,n) {
if(!dfn[i]) tarjan(i,0);
}
printf("Network #%d\n",t);
bool flag=1;
siji(i,1,n) {
if(is_AP[i]) {
printf(" SPF node %d leaves %d subnets\n",i,cnt[i]);
flag=0;
}
}
if(flag) {
puts(" No SPF nodes");
}
puts("");
}
}
Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and drinking with the other knights are fun things to do. Therefore, it is not very surprising that in recent years the kingdom of King Arthur has experienced an unprecedented increase in the number of knights. There are so many knights now, that it is very rare that every Knight of the Round Table can come at the same time to Camelot and sit around the round table; usually only a small group of the knights isthere, while the rest are busy doing heroic deeds around the country.
Knights can easily get over-excited during discussions-especially after a couple of drinks. After some unfortunate accidents, King Arthur asked the famous wizard Merlin to make sure that in the future no fights break out between the knights. After studying the problem carefully, Merlin realized that the fights can only be prevented if the knights are seated according to the following two rules:
The knights should be seated such that two knights who hate each other should not be neighbors at the table. (Merlin has a list that says who hates whom.) The knights are sitting around a roundtable, thus every knight has exactly two neighbors.
An odd number of knights should sit around the table. This ensures that if the knights cannot agree on something, then they can settle the issue by voting. (If the number of knights is even, then itcan happen thatyes" and
no" have the same number of votes, and the argument goes on.)
Merlin will let the knights sit down only if these two rules are satisfied, otherwise he cancels the meeting. (If only one knight shows up, then the meeting is canceled as well, as one person cannot sit around a table.) Merlin realized that this means that there can be knights who cannot be part of any seating arrangements that respect these rules, and these knights will never be able to sit at the Round Table (one such case is if a knight hates every other knight, but there are many other possible reasons). If a knight cannot sit at the Round Table, then he cannot be a member of the Knights of the Round Table and must be expelled from the order. These knights have to be transferred to a less-prestigious order, such as the Knights of the Square Table, the Knights of the Octagonal Table, or the Knights of the Banana-Shaped Table. To help Merlin, you have to write a program that will determine the number of knights that must be expelled.
The input contains several blocks of test cases. Each case begins with a line containing two integers 1 ≤ n ≤ 1000 and 1 ≤ m ≤ 1000000 . The number n is the number of knights. The next m lines describe which knight hates which knight. Each of these m lines contains two integers k1 and k2 , which means that knight number k1 and knight number k2 hate each other (the numbers k1 and k2 are between 1 and n ).
The input is terminated by a block with n = m = 0 .
For each test case you have to output a single integer on a separate line: the number of knights that have to be expelled.
5 5
1 4
1 5
2 5
3 4
4 5
0 0
2
Huge input file, 'scanf' recommended to avoid TLE.
这道题是一个非常厉害的题……总和了很多知识点
还让我发现了…原来我根本不会写双联通分量
首先憎恨关系这个很难处理,所以我们可以考虑,建一个反图,也就是非憎恨关系,我们将没有憎恨关系的人连边
然后跑一个双联通分量,这个双联通分量需要有奇数个点的环,也就是奇环,有了一个奇环保证了整个双联通分量的每个点都在一个奇环里,那么有奇环用什么判断,二分图染色,如果染色不成功,那么必然是合法的,否则这一整个双联通分量都不能要
那么我到底跪在哪里了呢,因为我双联通分量求错了,双联通分量需要一个栈,在low[v]>=dfn[u]的时候出去一个双联通分量,然而这个栈弹出的时候只能弹到v点,而不能从v点继续往下弹,因为u点可能还遍历过别的出边,这个出边指向的点还在栈里,如果弹到u这个出边指向的点就会被错误的弹出
例如这么一组数据
5 10
3 1
2 4
2 1
1 1
1 3
1 1
2 1
1 3
1 1
4 3
0 0
答案是0,但是极有可能,5先遍历到了4,然后弹出2 3 时为了找到5把4也弹出了
因为是多组数据所以栈要清一遍!!!!
QAQ
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 2005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
struct node {
int to,next;
}edge[MAXN*MAXN*2];
int head[MAXN],sumedge;
int n,m;
int dfn[MAXN],low[MAXN],inx,col[MAXN],tot;
int flag[MAXN],ans,st[MAXN],top;
bool choose[MAXN],vis[MAXN][MAXN];
vector<int> vi;
bool dfs(int u) {
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(col[v]==col[u]) {
if(!flag[v]) {
flag[v]=flag[u]^1;
if(!dfs(v)) return false;
}
else if(flag[u]==flag[v]){
return false;
}
}
}
return true;
}
void tarjan(int u) {
dfn[u]=low[u]=++inx;
st[++top]=u;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(!dfn[v]) {
tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]) {
vi.clear();
int cnt=0;
++tot;
while(st[top+1]!=v) {
int x=st[top];
vi.push_back(x);
col[x]=tot;
--top;
++cnt;
}
vi.push_back(u);
col[u]=tot;
++cnt;
if(cnt<3) {
continue;
}
flag[u]=2;
if(!dfs(u)) {
xiaosiji(j,0,cnt) {
choose[vi[j]]=1;
}
}
col[u]=0;
flag[u]=0;
}
}
else{
low[u]=min(dfn[v],low[u]);
}
}
}
void add(int u,int v) {
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
void addtwo(int u,int v) {
add(u,v);add(v,u);
}
void solve() {
memset(head,0,sizeof(head));
sumedge=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
inx=0;
memset(choose,0,sizeof(choose));
memset(vis,0,sizeof(vis));
memset(col,0,sizeof(col));
memset(flag,0,sizeof(flag));
ans=0;
tot=0;
int u,v;
siji(i,1,m) {
u=read();v=read();
vis[u][v]=1;
vis[v][u]=1;
}
siji(i,1,n) {
siji(j,i+1,n) {
if(!vis[i][j]) addtwo(i,j);
}
}
siji(i,1,n) {
top=0;
memset(st,0,sizeof(st));
if(!dfn[i]) tarjan(i);
}
siji(i,1,n) {
if(!choose[i]) ++ans;
}
printf("%d\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
while(1) {
n=read();m=read();
if(n==0 && m==0) break;
solve();
}
}
也就是对于有一些集合,每个集合里有两个元素,我们对于每个集合只能选一个,这些元素之间有一些对立关系
k-SAT是一个NP问题,而2-SAT有一些特殊的方法
我们对于四种常见模型可以采取以下的方法连边
思路是对每个元素都建一个点
那么选了A必须选B',选了B必须选A'
A->B' B->A'
那么选了A'必须选B,选了B'必须选A
A'->B B'->A
那么选了A'必须选B',选了B'必须选A',选了A必须选B,选了B必须选A
A'->B' B'->A' A->B B->A
A’->A
选了A'必须选A,保证了A拓扑序在前
解的多解依赖于拓扑序的多情况,这样的话去除了A'在A前面的情况
然后我们对于这些点跑tarjan,跑完之后缩点,缩点之后存反边,然后拓扑排序
但是这一步其实不必要,因为反边之后的拓扑序就是求tarjan时点编号的正序,这个问题就完美解决了
也就是说2-SAT就是——tarjan求强连通分量!
Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a boolean operator op (one of AND, OR, XOR) and an integer c (0 ≤ c ≤ 1). One Katu is solvable if one can find each vertex Vi a value Xi (0 ≤ Xi ≤ 1) such that for each edge e(a, b) labeled by op and c, the following formula holds:
Xa op Xb = c
The calculating rules are:
AND 0 1
0 0 0
1 0 1
OR 0 1
0 0 1
1 1 1
XOR 0 1
0 0 1
1 1 0
Given a Katu Puzzle, your task is to determine whether it is solvable.
The first line contains two integers N (1 ≤ N ≤ 1000) and M,(0 ≤ M ≤ 1,000,000) indicating the number of vertices and edges.
The following M lines contain three integers a (0 ≤ a < N), b(0 ≤ b < N), c and an operator op each, describing the edges.
Output a line containing "YES" or "NO".
4 4
0 1 1 AND
1 2 1 OR
3 2 0 AND
3 0 0 XOR
YES
X0 = 1, X1 = 1, X2 = 0, X3 = 1.
这道题的思路很明显
如果是AND 1
a的0 连到a的1
b的0连到b的1
a的1连到b的1
b的1连到a的1
如果AND 0
a的1连到b的0
b的1连到a的0
如果OR 1
a的0连到b的1
b的0连到a的1
如果OR 0
a的1连到a的0
b的1连到b的0
a的0连到b的0
b的0连到a的0
如果XOR 1
a的0连到b的1
a的1连到b的0
b的1连到a的0
b的0连到a的1
如果XOR 0
a的0连到b的0
b的0连到a的0
a的1连到b的1
b的1连到a的1
然而我这个傻逼……tarjan写错了!!!!!
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 10005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
struct node {
int to,next;
}edge[4000005];
int head[MAXN*2],sumedge;
int n,m;
int dfn[MAXN*2],low[MAXN*2],inx,instack[MAXN*2],col[MAXN*2],tot;
stack<int> st;
void add(int u,int v) {
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
void addtwo(int u,int v) {
add(u,v);add(v,u);
}
void tarjan(int u) {
dfn[u]=low[u]=++inx;
st.push(u);
instack[u]=1;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(!dfn[v]) {
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v]==1) {
low[u]=min(dfn[v],low[u]);
}
}
if(low[u]==dfn[u]) {
++tot;
int x;
while(1) {
x=st.top();st.pop();
col[x]=tot;
instack[x]=2;
if(x==u) break;
}
}
}
void solve() {
n=read();m=read();
int a,b,c;
char op[10];
siji(i,1,m) {
scanf("%d%d%d",&a,&b,&c);;
scanf("%s",op+1);
++a;++b;
if(op[1]=='A') {
if(c==1) {//must choose 1
add(a*2-1,a*2);
add(b*2-1,b*2);
add(a*2,b*2);
add(b*2,a*2);
}
else {
add(a*2,b*2-1);
add(b*2,a*2-1);
}
}
else if(op[1]=='O') {
if(c==1) {
add(a*2-1,b*2);
add(b*2-1,a*2);
}
else {//must choose 0
add(a*2,a*2-1);
add(b*2,b*2-1);
add(a*2-1,b*2-1);
add(b*2-1,a*2-1);
}
}
else {
if(c==1) {
add(a*2-1,b*2);
add(b*2-1,a*2);
add(b*2,a*2-1);
add(a*2,b*2-1);
}
else {
add(a*2,b*2);
add(b*2,a*2);
add(a*2-1,b*2-1);
add(b*2-1,a*2-1);
}
}
}
siji(i,1,2*n) {
if(!dfn[i]) {
tarjan(i);
}
}
siji(i,1,n) {
if(col[i*2-1]==col[i*2] && col[i*2-1]!=0) {
puts("NO");
return;
}
}
puts("YES");
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
Farmer John's farm has N barns, and there are some cows that live in each barn. The cows like to drop around, so John wants to build some roads to connect these barns. If he builds roads for every pair of different barns, then he must build N * (N - 1) / 2 roads, which is so costly that cheapskate John will never do that, though that's the best choice for the cows.
Clever John just had another good idea. He first builds two transferring point S1 and S2, and then builds a road connecting S1 and S2 and N roads connecting each barn with S1 or S2, namely every barn will connect with S1 or S2, but not both. So that every pair of barns will be connected by the roads. To make the cows don't spend too much time while dropping around, John wants to minimize the maximum of distances between every pair of barns.
That's not the whole story because there is another troublesome problem. The cows of some barns hate each other, and John can't connect their barns to the same transferring point. The cows of some barns are friends with each other, and John must connect their barns to the same transferring point. What a headache! Now John turns to you for help. Your task is to find a feasible optimal road-building scheme to make the maximum of distances between every pair of barns as short as possible, which means that you must decide which transferring point each barn should connect to.
We have known the coordinates of S1, S2 and the N barns, the pairs of barns in which the cows hate each other, and the pairs of barns in which the cows are friends with each other.
Note that John always builds roads vertically and horizontally, so the length of road between two places is their Manhattan distance. For example, saying two points with coordinates (x1, y1) and (x2, y2), the Manhattan distance between them is |x1 - x2| + |y1 - y2|.
The first line of input consists of 3 integers N, A and B (2 <= N <= 500, 0 <= A <= 1000, 0 <= B <= 1000), which are the number of barns, the number of pairs of barns in which the cows hate each other and the number of pairs of barns in which the cows are friends with each other.
Next line contains 4 integer sx1, sy1, sx2, sy2, which are the coordinates of two different transferring point S1 and S2 respectively.
Each of the following N line contains two integer x and y. They are coordinates of the barns from the first barn to the last one.
Each of the following A lines contains two different integers i and j(1 <= i < j <= N), which represent the i-th and j-th barns in which the cows hate each other.
The same pair of barns never appears more than once.
Each of the following B lines contains two different integers i and j(1 <= i < j <= N), which represent the i-th and j-th barns in which the cows are friends with each other. The same pair of barns never appears more than once.
You should note that all the coordinates are in the range [-1000000, 1000000].
You just need output a line containing a single integer, which represents the maximum of the distances between every pair of barns, if John selects the optimal road-building scheme. Note if there is no feasible solution, just output -1.
4 1 1
12750 28546 15361 32055
6706 3887
10754 8166
12668 19380
15788 16059
3 4
2 3
53246
2-SAT不能做带限制的东西
然而这个东西……要求最大值最小
这让我们想到二分答案!
2-SAT当然是只能判可行解啦!!!
然后我们判断两个点链接方式的不同会不会大于我们二分到的答案,然后根据这新得的限制关系判断是否可行
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <cmath>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 10005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
struct node {
int to,next;
}edge[4000005];
int head[MAXN*2],sumedge;
int dfn[MAXN*2],low[MAXN*2],inx,instack[MAXN*2],col[MAXN*2],tot;
stack<int> st;
void add(int u,int v) {
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
void addtwo(int u,int v) {
add(u,v);add(v,u);
}
void tarjan(int u) {
dfn[u]=low[u]=++inx;
st.push(u);
instack[u]=1;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(!dfn[v]) {
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v]==1) {
low[u]=min(dfn[v],low[u]);
}
}
if(low[u]==dfn[u]) {
++tot;
int x;
while(1) {
x=st.top();st.pop();
col[x]=tot;
instack[x]=2;
if(x==u) break;
}
}
}
int dis;
int x[MAXN],y[MAXN],n,A,B,c[MAXN],d[MAXN];
int dist(int l,int z) {
return abs(x[l]-x[z])+abs(y[l]-y[z]);
}
bool check(int limit) {
sumedge=0;
tot=0;
inx=0;
memset(head,0,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(col,0,sizeof(col));
memset(instack,0,sizeof(instack));
siji(i,1,A) {
add(c[i],d[i]+n);
add(d[i],c[i]+n);
add(c[i]+n,d[i]);
add(d[i]+n,c[i]);
}
siji(i,A+1,A+B) {
add(c[i],d[i]);
add(d[i],c[i]);
add(c[i]+n,d[i]+n);
add(d[i]+n,c[i]+n);
}
siji(i,1,n) {
siji(j,i+1,n) {
if(dist(i,n+1)+dist(j,n+1) > limit) {
add(i,j+n);
add(j,i+n);
}
if(dist(i,n+2)+dist(j,n+2) > limit) {
add(i+n,j);
add(j+n,i);
}
if(dist(i,n+1)+dist(j,n+2)+dis > limit) {
add(i,j);
add(j+n,i+n);
}
if(dist(i,n+2)+dist(j,n+1)+dis > limit) {
add(i+n,j+n);
add(j,i);
}
}
}
siji(i,1,2*n) {
if(!dfn[i]) {
tarjan(i);
}
}
siji(i,1,n) {
if(col[i]==col[i+n]) return false;
}
return true;
}
void solve() {
n=read();
A=read();
B=read();
x[n+1]=read();y[n+1]=read();x[n+2]=read();y[n+2]=read();
dis=abs(x[n+1]-x[n+2])+abs(y[n+1]-y[n+2]);
siji(i,1,n) {
x[i]=read();y[i]=read();
}
siji(i,1,A+B) {
c[i]=read();d[i]=read();
}
int l=0,r=10000000;
while(l<r) {
int mid=(l+r)>>1;
if(check(mid)) {
r=mid;
}
else {
l=mid+1;
}
}
if(l==10000000) {
puts("-1");
return;
}
printf("%d\n",r);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}