生活随笔
收集整理的這篇文章主要介紹了
牛客九 J-Jam
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
牛客九 J-Jam
題意大概是一個十字路口,從每一個方向來的車會駛入其余的三個方向,總共有12種方向。給定每個方向車流的數量ci,jc_{i,j}ci,j?,問需要多少的單位時間可以使所有車輛駛過這個路口,并且要滿足車流不能交錯(如不能一邊W->E一邊N->S)。
數據范圍:0<=ci,j<=1000<=c_{i,j}<=1000<=ci,j?<=100
題意不是很好理解,但是如果平時對于十字路口的信號燈有觀察的話還是會大致明白這個題需要做什么。
在剔除了所有的右轉之后,剩下八種車流,他們互相有著約束的關系,最后確定可以有十二種方案可以使兩種車流同時通過。在比賽的時候,想的是一個整數規劃,也就是以方案為變量,總共十二個變量,八個約束,但是整數規劃不會,不知道怎么搞(或許可以先用單純性然后找附近整點?)。亂搞了一個蒙特卡洛但是范圍太大很難隨機對,不是WA就是TLE。
打完后得知是用枚舉的方式刪掉兩條邊之后得到一個二分圖,再跑網絡流。
大概就是上面的這種圖,可以發現,如果刪掉7-8和3-4兩條邊,那么可以將左右兩邊分開,形成一個二分圖。先枚舉刪掉的兩條邊的流量,將7,8兩點和3,4兩點分別減去之后,連接源點和匯點跑網絡流,最后的最大流和之前枚舉的兩條邊之和就是總共的可以兩個方向的車輛同時通過的時間,用總的車流量去減,求最小值即為答案。
#include <bits/stdc++.h>
using namespace std
;const int N
= 5, inf
= 1e9;
int flow
[N
][N
], b
[N
<< 1], a
[N
<< 2], num
;
int head
[20], s
, t
, dep
[20], now
[20];struct edge
{int nxt
, to
, flo
;
};
edge e
[50];void addEdge(int x
, int y
, int z
)
{e
[++ num
].nxt
= head
[x
];head
[x
] = num
;e
[num
].to
= y
;e
[num
].flo
= z
;e
[++ num
].nxt
= head
[y
];head
[y
] = num
;e
[num
].to
= x
;e
[num
].flo
= 0;
}bool bfs()
{memset (dep
, -1, sizeof (dep
));dep
[s
] = 0;queue
<int> q
;q
.push(s
);while (!q
.empty()){int x
= q
.front(); q
.pop();for (int i
= head
[x
]; i
!= -1; i
= e
[i
].nxt
){int to
= e
[i
].to
;if (dep
[to
] == -1 && e
[i
].flo
> 0){dep
[to
] = dep
[x
] + 1;q
.push(to
);}}}if (dep
[t
] == -1)return false;return true;
}int dfs(int x
, int f
)
{if (x
== t
)return f
;for (int i
= now
[x
]; i
!= -1; i
= e
[i
].nxt
){now
[x
] = i
;int to
= e
[i
].to
;if (e
[i
].flo
> 0 && dep
[to
] == dep
[x
] + 1){int val
= dfs(to
, min(f
, e
[i
].flo
));if (val
> 0){e
[i
].flo
-= val
;e
[i
^ 1].flo
+= val
;return val
;}}}return 0;
}int dinic(int x
, int y
)
{int ans
= 0, val
;s
= x
; t
= y
;while(bfs()){for (int i
= 0; i
<= 9; i
++)now
[i
] = head
[i
];while (val
= dfs(s
, inf
)){ans
+= val
;}}return ans
;
}int main()
{ios
::sync_with_stdio(false);cin
.tie(0);srand(time(0));int T
= 1;cin
>> T
;while (T
--){for (int i
= 1; i
<= 4; i
++)for (int j
= 1; j
<= 4; j
++)cin
>> flow
[i
][j
];b
[1] = flow
[1][3]; b
[2] = flow
[1][2];b
[3] = flow
[2][4]; b
[4] = flow
[2][3];b
[5] = flow
[3][1]; b
[6] = flow
[3][4];b
[7] = flow
[4][2]; b
[8] = flow
[4][1];int ans
= inf
, ans1
= max(max(flow
[1][4], flow
[2][1]), max(flow
[3][2], flow
[4][3]));int sum
= 0;for (int i
= 1; i
<= 8; i
++)sum
+= b
[i
];for (int i
= 0; i
<= min(b
[7], b
[8]); i
++)for (int j
= 0; j
<= min(b
[3], b
[4]); j
++){memset (head
, -1, sizeof (head
));num
= -1;addEdge(0, 1, b
[1]);addEdge(0, 6, b
[6]);addEdge(0, 7, b
[7] - i
);addEdge(0, 8, b
[8] - i
);addEdge(2, 9, b
[2]);addEdge(5, 9, b
[5]);addEdge(3, 9, b
[3] - j
);addEdge(4, 9, b
[4] - j
);addEdge(1, 2, inf
);addEdge(1, 4, inf
);addEdge(1, 5, inf
);addEdge(6, 2, inf
);addEdge(6, 3, inf
);addEdge(6, 5, inf
);addEdge(7, 2, inf
);addEdge(7, 3, inf
);addEdge(8, 4, inf
);addEdge(8, 5, inf
);int val
= dinic(0, 9);val
+= i
+ j
;ans
= min(ans
, sum
- val
);}cout
<< max(ans
, ans1
) << "\n";}return 0;
}
總結
以上是生活随笔為你收集整理的牛客九 J-Jam的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。