日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

hdu1815 2sat + 二分 + 建图不错的题目

發(fā)布時間:2025/6/17 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu1815 2sat + 二分 + 建图不错的题目 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題意:
? ? ? 給你兩個總部,s1 ,s2,和n個點,任意兩點之間都是通過這個總部相連的,其中有一些點不能連在同一個總部上,有一些點可以連接在同一個總部上,總部和總部之間可以直接連接,就是假如a,b相連,可以使這樣四中情況中的一種
a-s1 ?s1 - b
a-s2 ?s2 - b
a-s1 ?s1 - s2 ?s2 - b
a-s2 ?s2 - s1 ?s1 - b
最后問你任意ab距離最遠的最近是多少。


思路:
? ? ? 首先這個題目的總部有兩個,還有一些限制關系,那么很容易就想到2sat問題,關鍵是怎么建邊,怎樣找到限制關系,還是舉例子說容易懂,
s_x1[i] : 表示i點到S1的距離。
s_x2[i] : 表示i點到S2的距離。
D 表示S1,S2的距離。

彼此厭惡 x -> ~y ,y -> ~x ,~y -> x ,~x -> y
彼此喜歡 x -> y ,~x -> ~y ,y -> x ,~y -> ~x


s_x1[x] + s_x1[y] > mid ? ? ? ? ?x -> ~y ,y -> ~x

s_x2[x] + s_x2[y] > mid ? ? ? ? ?~x -> y ,~y -> x
s_x1[x] + s_x2[y] + D > mid ? ? ?x -> y ,~y -> ~x
s_x2[x] + s_x1[y] + D > mid ? ? ?~x -> ~y ,y -> x


每次二分就這么建邊就ok了,還有提示下,之前在網(wǎng)上看到有個人的題解是直接先跑了便彼此厭惡和喜歡的,然后二分的時候就不管那個了,那個我感覺正確性說不通,我是每次都全部從新建邊的,上面的如果寫錯了請大家留言指教,互相學習。


#include<stdio.h> #include<string.h> #include<stack>#define N_node 1000 + 10 #define N_edge 5000000 + 300 using namespace std;typedef struct {int to ,next; }STAR;typedef struct {int x ,y; }NODE;STAR E1[N_edge] ,E2[N_edge]; NODE S1 ,S2 ,A; int s_x1[550] ,s_x2[550]; int list1[N_node] ,list2[N_node] ,tot; int Belong[N_node] ,cnt; int mark[N_node]; int F[1100][2] ,NF[1100][2]; stack<int>st;void add(int a ,int b) {E1[++tot].to = b;E1[tot].next = list1[a];list1[a] = tot;E2[tot].to = a;E2[tot].next = list2[b];list2[b] = tot; }void DFS1(int s) {mark[s] = 1;for(int k = list1[s] ;k ;k = E1[k].next)if(!mark[E1[k].to]) DFS1(E1[k].to);st.push(s); }void DFS2(int s) {mark[s] = 1;Belong[s] = cnt;for(int k = list2[s] ;k ;k = E2[k].next)if(!mark[E2[k].to]) DFS2(E2[k].to); }int abss(int x) {return x > 0 ? x : -x; }int dis(NODE a ,NODE b) {return abss(a.x - b.x) + abss(a.y - b.y); }bool ok(int mid ,int n ,int m ,int q) {memset(list1 ,0 ,sizeof(list1));memset(list2 ,0 ,sizeof(list2));tot = 1;for(int i = 1 ;i <= m ;i ++){int x = NF[i][0] * 2 ,xx = NF[i][0] * 2 + 1;int y = NF[i][1] * 2 ,yy = NF[i][1] * 2 + 1;add(x ,yy) ,add(y ,xx);add(yy ,x) ,add(xx ,y);}for(int i = 1 ;i <= q ;i ++){int x = F[i][0] * 2 ,xx = F[i][0] * 2 + 1;int y = F[i][1] * 2 ,yy = F[i][1] * 2 + 1;add(x ,y) ,add(xx ,yy);add(y ,x) ,add(yy ,xx);}int D = dis(S1 ,S2);for(int i = 0 ;i < n ;i ++)for(int j = i + 1 ;j < n ;j ++){int x = i * 2 ,xx = i * 2 + 1;int y = j * 2 ,yy = j * 2 + 1;if(s_x1[i] + s_x1[j] > mid) add(x ,yy) ,add(y ,xx);if(s_x2[i] + s_x2[j] > mid) add(xx ,y) ,add(yy ,x);if(s_x1[i] + s_x2[j] + D > mid) add(x ,y) ,add(yy ,xx);if(s_x2[i] + s_x1[j] + D > mid) add(xx ,yy) ,add(y ,x);}memset(mark ,0 ,sizeof(mark));while(!st.empty()) st.pop();for(int i = 0 ;i < n * 2 ;i ++)if(!mark[i]) DFS1(i);memset(mark ,0 ,sizeof(mark));cnt = 0;while(!st.empty()){int xin = st.top();st.pop();if(mark[xin]) continue;++ cnt;DFS2(xin);}int mk = 0;for(int i = 0 ;i < n * 2 && !mk;i += 2)if(Belong[i] == Belong[i^1]) mk = 1;return !mk; }int main () {int n ,m ,q;int i ,low ,mid ,up;while(~scanf("%d %d %d" ,&n ,&m ,&q)){scanf("%d %d %d %d" ,&S1.x ,&S1.y ,&S2.x ,&S2.y);low = up = 8000000;for(i = 0 ;i < n ;i ++){scanf("%d %d" ,&A.x ,&A.y);s_x1[i] = dis(A ,S1);s_x2[i] = dis(A ,S2);if(low > s_x1[i]) low = s_x1[i];if(low > s_x2[i]) low = s_x2[i];}for(i = 1 ;i <= m ;i ++){scanf("%d %d" ,&NF[i][0] ,&NF[i][1]);NF[i][0] -- ,NF[i][1] --;}for(i = 1 ;i <= q ;i ++){scanf("%d %d" ,&F[i][0] ,&F[i][1]);F[i][0] -- ,F[i][1] -- ;}int ans = -1;while(low <= up){mid = (low + up) >> 1;if(ok(mid ,n ,m ,q))ans = mid ,up = mid - 1;else low = mid + 1;}printf("%d\n" ,ans);}return 0; }







總結

以上是生活随笔為你收集整理的hdu1815 2sat + 二分 + 建图不错的题目的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。