Description
In last winter, there was a big snow storm in South China. The electric system was damaged seriously. Lots of power lines were broken and lots of villages lost contact with the main power grid. The government wants to reconstruct the electric system as soon as possible. So, as a professional programmer, you are asked to write a program to calculate the minimum cost to reconstruct the power lines to make sure there's at least one way between every two villages.
Input
Standard input will contain multiple test cases. The first line of the input is a single integer T (1 <= T <= 50) which is the number of test cases. And it will be followed by T consecutive test cases.
In each test case, the first line contains two positive integers N and E (2 <= N <= 500, N <= E <= N * (N - 1) / 2), representing the number of the villages and the number of the original power lines between villages. There follow E lines, and each of them contains three integers, A, B, K (0 <= A, B < N, 0 <= K < 1000). A and B respectively means the index of the starting village and ending village of the power line. If K is 0, it means this line still works fine after the snow storm. If K is a positive integer, it means this line will cost K to reconstruct. There will be at most one line between any two villages, and there will not be any line from one village to itself.
Output
For each test case in the input, there's only one line that contains the minimum cost to recover the electric system to make sure that there's at least one way between every two villages.
Sample Input
1 3 3 0 1 5 0 2 0 1 2 9
Sample Output
5
这道题裸的最小生成树。。唯一坑的是点从0开始!!刚开始我从1开始WA了2次。。以后读题要仔细
#include
#include
#include
using namespace std;
struct edge{
int u,v,w;
bool operator <(const edge &a)const{return this -> w < a.w;}
}e[125000 + 5];
int T;
int fa[500 + 5];
int n,E;
int find(int x){
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
int kruskal(){
int ans = 0;
for(int i = 1,count = 1; i <= E && count <= n; ++i){
int x = find(e[i].u),y = find(e[i].v);
if(x != y){
fa[x] = y;
count++;
ans += e[i].w;
}
}
return ans;
}
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d%d",&n, &E);
for(int i = 0; i < n; ++i)fa[i] = i;
for(int i = 1; i <= E; ++i){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
sort(e + 1, e + 1 + E);
printf("%d\n",kruskal());
}
return 0;
}
Description
Input
Output
Sample Input
1 4 10000 3 2 2 8000 3 5000 1000 2 1 4 200 3000 2 1 4 200 50 2 0
Sample Output
5250
#include
#include
#include
#include
#include
using namespace std;
struct egde{
int v,w,next;
}e[100*100 + 5];
typedef pairpii;
bool vis[100 + 5];
int p[100 + 5],l[100 + 5],x[100 + 5];
int dis[100 + 5];
priority_queue, greater >q;
int ans = 0x3f3f3f3f;
int m,n;
int head[100 + 5],k = 1;
void adde(int u,int v,int w)
{
e[k].v = v;
e[k].w = w;
e[k].next = head[u];
head[u] = k++;
}
int abs(int a){
return a <= 0 ? -a : a;
}
int dijkstra(int x)
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[x] = p[x];q.push(make_pair(dis[x],x));vis[x] = 1;
while(q.size()){
int u = q.top().second;q.pop();
for(int i = head[u]; i ; i = e[i].next){
int v = e[i].v;
if(abs(l[u] - l[v]) <= m && abs(l[x] - l[v]) <= m && (abs(l[v] - l[1]) <= m) && abs(l[u] - l[1]) <= m){
if(dis[v] > dis[u] + e[i].w)
dis[v] = dis[u] + e[i].w;
if(!vis[v]){
vis[v] = 1;
q.push(make_pair(dis[v],v));
}
}
}
}
return dis[1];
}
int main()
{
while(~scanf("%d%d",&m,&n)){
ans = 0x3f3f3f3f;
for(int i = 1; i <= n; ++i){
scanf("%d%d%d",&p[i],&l[i],&x[i]);
for(int j = 1; j <= x[i]; ++j){
int t,v;
scanf("%d%d",&t,&v);
adde(t,i,v);
}
}
for(int i = 1; i <= n; ++i)
ans = min(ans,dijkstra(i));
if(ans == 0x3f3f3f3f)printf("%d\n",p[1]);
else printf("%d\n",ans);
}
return 0;
}
Ronju is a night-guard at the “Lavish office buildings Ltd.” headquarters. The office has a large grassfield in front of the building. So every day, when Ronju comes to duty at the evening, it is his dutyto turn on all the lights in the field. However, given the large size of the field and the large number oflights, it is very tiring for him to walk to each and every individual light to turn it on.So he has devised an ingenious plan — he will swap the switches for light-sensitive triggers. Alocal electronic store nearby sells these funny trigger switches at a very cheap price. Once installed ata light-post, it will automatically turn that light on whenever it can sense some other light lightingup nearby. So from now on, Ronju can just manually flip a few switches, and the light from thosewill trigger nearby sensors, which will in turn light up some more lights nearby, and so on, graduallylighting up the whole field.Now Ronju wonders: how many switches does he have to flip manually for this?
Input
The input starts with an integer T, the number of test cases to follow. Each test case will start withtwo integers N (1 ≤ N ≤ 10000) and M (0 ≤ M ≤ 100000), where N is the number of lights in thefield, and M more lines of input follows in this input case. Each of these extra M lines will have twointegers a and b separated by a space, where 1 ≤ a, b ≤ N, indicating that if the light a lights up, itwill trigger the light b to turn on as well (according to their distance, brightness, sensor sensitivity,orientation and other complicated factors).Finally, every test case in the input will be followed by a blank line.
Output
For each input test case, the output must be a single line of the format ‘Case k: c’ where k is thecase number starting with 1, and c is the minimum number of lights that Ronju must turn on manuallybefore all the lights in the whole field gets lit up.
Sample Input
2
5 4
1 2
1 3
3 4
5 3
4 4
1 2
1 3
4 2
4 3
Sample Output
Case 1: 2
Case 2: 2
这道题直接tarjan+缩点,然后找入度为0的点的个数就好了,会了tarjan的就是一道裸题,不会的。。。去学吧
#include
#include
#include
#include
#include
#define mem(x,a) memset(x,a,sizeof(x))
using namespace std;
int T;
int n,m;
vectore[10000 + 5];
bool vis1[10000 + 5];//标记是否访问过
bool vis2[10000 + 5];//标记是否在栈中
int dfn[10000 + 5],low[10000 + 5];//dfn[u]为到u的次序数,low[u]为能直接或间接到达的次序数
int belong[10000 + 5];//缩点后每个点属于哪个点
int in[10000 + 5];
stackq;
int id = 1,node = 0;;
void init(){
for(int i = 1;i <= n; ++i)
e[i].clear();
node = 0;
id = 1;
mem(vis1,0);
mem(vis2,0);
mem(dfn,0);
mem(low,0);
mem(in,0);
while(q.size())q.pop();
}
void tarjan(int u){
dfn[u] = low[u] = id++;
vis1[u] = 1;q.push(u);vis2[u] = 1;
for(int i = 0; i < e[u].size(); ++i){
int v = e[u][i];
if(!vis1[v]){
tarjan(v);
low[u] = min(low[v],low[u]);
}
else if(vis2[v]) low[u] = min(dfn[v],low[u]);
}
if(low[u] == dfn[u]){
node++;
while(1){
int tmp = q.top();q.pop();
vis2[tmp] = 0;
belong[tmp] = node;
if(tmp == u)break;
}
}
}
int main()
{
scanf("%d",&T);
int cnt = 1;
while(T--){
int ans = 0;
scanf("%d%d",&n,&m);
init();
for(int i = 1; i <= m; ++i){
int a,b;
scanf("%d%d",&a,&b);
e[a].push_back(b);
}
for(int i = 1; i <= n; ++i){
if(!vis1[i])
tarjan(i);
}
for(int i = 1; i <= n; ++i){
for(int j = 0; j < e[i].size(); j++){
int v = e[i][j];
if(belong[i] != belong[v])
in[belong[v]]++;
}
}
for(int i = 1; i <= node; ++i){
if(!in[i])ans++;
}
printf("Case %d: %d\n",cnt++,ans);
}
return 0;
}
Michiel Adriaenszoon de Ruyter is the most famous admiral in Dutch history and is well known for hisrole in the Anglo-Dutch Wars of the 17th century. De Ruyter personally commanded a flagship andissued commands to allied warships during naval battles.In De Ruyter’s time, graph theory had just been invented and the admiral used it to his greatadvantage in planning his naval battles. Waypoints at sea are represented by vertices, and possiblepassages from one waypoint to another are represented as directed edges. Given any two waypointsW1 and W2 , there is at most one passage W1 → W2 . Each directed edge is marked with the numberof cannonballs that need to be fired in order to safely move a ship along that edge, sinking the enemyships encountered along the way.One of De Ruyter’s most successful tactics was the De Ruyter Manoeuvre. Here, two warships startat the same waypoint, and split up and fight their way through the enemy fleet, joining up again at adestination waypoint. The manoeuvre prescribes that the two warships take disjunct routes, meaningthat they must not visit the same waypoint (other than the start and end-points), or use the samepassage during the battle.Being Dutch, Admiral De Ruyter did not like to waste money; in 17th century naval warfare, thismeant firing as few expensive cannonballs as possible.Figure 1: A particular instance of De Ruyter’s tactic, visualised as a graph. Two ships (‘red’and ‘blue’) move from a shared starting point (1) to a shared endpoint (6). The red ship’s route is1 → 3 → 6 (firing 33 canonballs along the way); the blue ship’s route is 1 → 2 → 5 → 4 → 6 (firing53 canonballs along the way). In total, 86 canonballs are fired during the manoeuvre. Except for thestart- and end-point, no vertices or edges are visited by both ships.
Input
For each test case, the input consists of:• A line containing two integers v (3 ≤ v ≤ 1000) and e (3 ≤ e ≤ 10000), the number of waypointsand passages, respectively.• Then, e lines follow: for each passage, a line containing three integers:1. ai (1 ≤ ai ≤ v), the starting-point of a passage, which is represented by a waypoint;2. bi (1 ≤ bi ≤ v) and (ai ̸= bi), the end-point of a passage, which is represented by a waypoint.All passages are directed passages;3. ci (1 ≤ ci ≤ 100), the number of cannonballs that are fired when travelling along this passage.The starting waypoint is 1 and the destination waypoint is v. There are always at least two disjunctroutes from waypoint 1 to waypoint v.
Output
For each test case, the output consists of a single positive integer: the smallest possible sum of cannonballsfired by both ships when reaching the destination waypoint.
Sample Input
6 11
1 2 23
1 3 12
1 4 99
2 5 17
2 6 73
3 5 3
3 6 21
4 6 8
5 2 33
5 4 5
6 5 20
Sample Output
86
这道题是最小费用最大流,由于1,v都要经过两次,所以为最大流,这道题可以拆点,将一个点拆为入点和出点,在建一条由入点到出点的流量限制为1的有向边,这样就是这个点走后流量为0,就不能走了,那么1,v就是流量为2的两个点;
首先构造带权有向图w(f)。w(f)中路径pre上的各边权之和即为原图G中相应可改进路pre的费用。w(f)的最短路即为G中的最小费用可改进路。在w(f)中寻找最短路,若存在最短路,则得到G中相应的可改进路p,调整p,直到不存在最短路
#include
#include
#include
#include
#define mem(x,a) memset(x,a,sizeof(x))
using namespace std;
const int inf = 0x3f3f3f3f;
struct edge{
int u,v,f,c,next;
}e[50000 + 5];
bool vis[1000 * 2 + 5];
int pre[1000 * 2 + 5];//记录路径
int head[1000 * 2 + 5], k = 0;
int dis[1000 * 2 + 5];//代价
int n,m,S,T;
void init(){
mem(head,-1);
mem(pre,0);
k = 0;
}
void adde(int u,int v,int c,int f){//起点,终点,代价,流量
e[k] = (edge){u,v,f,c,head[u]};
head[u] = k++;
e[k] = (edge){v,u,0,-c,head[v]};//后向弧,正向弧编号 ^ 1
head[v] = k++;
}
bool spfa(){
mem(vis,0);
mem(dis,0x3f);
queueq;
dis[S] = 0;q.push(S);
while(q.size()){
int u = q.front();q.pop();
vis[u] = 0;
for(int i = head[u]; i != -1 ; i = e[i].next){
int v = e[i].v;
if(e[i].f && dis[v] > dis[u] + e[i].c){
pre[v] = i;
dis[v] = e[i].c + dis[u];
if(!vis[v]){
vis[v] = 1;
q.push(v);
}
}
}
}
return dis[T] != inf;
}
void work(){
int cost = 0;
while(spfa()){//不断找最短路直到不能找到为止,若存在最短路,则得到图中中相应的可改进路pre
int a = inf;
for(int i = T; i != S; i = e[pre[i]].u){
a = min(a,e[pre[i]].f);
}
for(int i = T; i != S; i = e[pre[i]].u){
e[pre[i]].f -= a;
e[pre[i] ^ 1].f += a;//后向弧流量加
}
cost += a * dis[T];
}
printf("%d\n",cost);
}
int main()
{
while(~scanf("%d%d",&n,&m)){
init();
S = 1,T = 2 * n;//拆点,入点和出点,入点为i * 2 - 1,出点为i * 2
//入点和出点相连,中间加流量限制
adde(1, 2, 0, 2);
adde(n * 2 - 1, n * 2, 0, 2);//起点,终点的流量为2,其余点为1;
for(int i = 2; i < n; ++i)adde(i * 2 - 1, i * 2, 0, 1);
for(int i = 1; i <= m; ++i){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
adde(a * 2, b * 2 - 1, c, 1);//a的出点和b的入点相连
}
work();
}
return 0;
}