POJ 1486 Sorting Slides 二分图关键边 匈牙利算法
2017-07-30 09:42
686 查看
Professor Clumsey is going to give an important talk this afternoon. Unfortunately, he is not a very tidy person and has put all his transparencies on one big heap. Before giving the talk, he has to sort the slides. Being a kind
of minimalist, he wants to do this with the minimum amount of work possible.
The situation is like this. The slides all have numbers written on them according to their order in the talk. Since the slides lie on each other and are transparent, one cannot see on which slide each number is written.
Well, one cannot see on which slide a number is written, but one may deduce which numbers are written on which slides. If we label the slides which characters A, B, C, ... as in the figure above, it is obvious that D has number 3, B has number 1, C number 2
and A number 4.
Your task, should you choose to accept it, is to write a program that automates this process.
Input
The input consists of several heap descriptions. Each heap descriptions starts with a line containing a single integer n, the number of slides in the heap. The following n lines contain four integers xmin, xmax, ymin and ymax,
each, the bounding coordinates of the slides. The slides will be labeled as A, B, C, ... in the order of the input.
This is followed by n lines containing two integers each, the x- and y-coordinates of the n numbers printed on the slides. The first coordinate pair will be for number 1, the next pair for 2, etc. No number will lie on a slide boundary.
The input is terminated by a heap description starting with n = 0, which should not be processed.
Output
For each heap description in the input first output its number. Then print a series of all the slides whose numbers can be uniquely determined from the input. Order the pairs by their letter identifier.
If no matchings can be determined from the input, just print the word none on a line by itself.
Output a blank line after each test case.
Sample Input
Sample Output
关键边 只需要对所有的边 尝试删除这条边 删完之后做匈牙利 如果还能得到最大匹配 ans=n 那么这个边不是关键边 否则就是关键边
PS:这题我写烦了 用有向的好写多了 无向的注意数组范围 2*maxlen 别小了
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<string>
#include<cmath>
#define ff(i,x,y) for(int i=x;i<y;i++)
#define maxlen 30
using namespace std;
int n;
struct nodepoint
{
int x;
int y;
};
struct nodess
{
struct nodepoint lu;
struct nodepoint rd;
};
nodess ss[maxlen];
nodepoint points[maxlen];
//vector<int> G[2 * maxlen]; //与i有边相连的点的集合
int G[2 * maxlen][2 * maxlen];
int check[2*maxlen];
int matching[2*maxlen];
/*
bool dfs(int x)
{
for(int i = 0; i < G[x].size(); i++)
{
int newpos = G[x][i];
if(check[newpos] == 0)
{
check[newpos] = 1;
if(matching[newpos] == -1 || dfs(matching[newpos]) == 1)
{
matching[newpos] = x;
matching[x] = newpos;
return true;
}
}
}//for
return false;
}*/
bool dfs(int x)
{
for(int i = 0; i < 2 * n; i++)
{
if(G[x][i] == 1 && check[i] == 0)
{
check[i] = 1;
if(matching[i] == -1 || dfs(matching[i])==1)
{
matching[i] = x;
matching[x] = i;
return true;
}
}
}//for
return false;
}
int main()
{
//freopen("test.txt", "r", stdin);
int key = 0;
while(1)
{
key++;
memset(G, 0, sizeof G);
//for(int i = 0; i < 2 * maxlen; i++)
//G[i].resize(0);
//输入
scanf("%d", &n);
if(n == 0)
break;
for(int i = 0; i < n; i++)
{
scanf("%d %d %d %d", &ss[i].lu.x, &ss[i].rd.x, &ss[i].lu.y, &ss[i].rd.y);
}
for(int i = 0; i < n; i++)
scanf("%d %d", &points[i].x, &points[i].y);
//构造图
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if((points[j].x >= ss[i].lu.x && points[j].x <= ss[i].rd.x) && (points[j].y >= ss[i].lu.y && points[j].y <= ss[i].rd.y))
{
//G[i].push_back(j + n); //点和面的等价化 面为0~n-1 点为n~2n-1
//G[j + n].push_back(i);
G[i][j + n] = 1;
G[j + n][i] = 1;
}
}
}
memset(matching, -1, sizeof matching);
int ans=0;
for(int k = 0; k < 2 * n; k++)
{
if(matching[k] == -1)
{
memset(check, 0, sizeof check);
check[k] = 1;
if(dfs(k) == true)
ans++;
}
}//求新的ans
//cout<<n<<" "<<ans<<endl;
/*
for(int i = 0; i < n; i++)
{
for(int j = n; j < 2*n; j++)
{
cout<<G[i][j]<<" ";
}
cout<<endl;
}*/
//输出
printf("Heap %d\n", key);
bool ifhave = 0;
for(int i = 0; i < n; i++)
{
for(int j = n; j < 2 * n; j++)
{
if(G[i][j] == 0)
continue;
//int newp = G[i][j];
//vector<int>::iterator it11 = find(G[i].begin(), G[i].end(), newp);
//vector<int>::iterator it22 = find(G[newp].begin(), G[newp].end(), i);
G[i][j] = 0;
G[j][i] = 0;
//G[i].erase(it11);//暂时删掉
//G[newp].erase(it22);
memset(matching, -1, sizeof matching);
int newans = 0;
for(int k = 0; k < 2 * n; k++)
{
if(matching[k] == -1)
{
memset(check, 0, sizeof check);
//check[k] = 1;
if(dfs(k) == 1)
newans++;
}
}//求新的ans
G[i][j] = 1;
G[j][i] = 1;
//G[i].insert(it11,newp);//放回来
//G[newp].insert(it22,i);
if(newans != ans) //关键边
{
//if(ifhave == 1) printf(" ");
printf("(%c,%d) ", 'A' + i, j + 1 - n);
ifhave = 1;
//break;
}
}
}
if(ifhave == 0)
printf("none\n");
else
printf("\n");
printf("\n");
}
//cout<<1<<endl;
return 0;
}
of minimalist, he wants to do this with the minimum amount of work possible.
The situation is like this. The slides all have numbers written on them according to their order in the talk. Since the slides lie on each other and are transparent, one cannot see on which slide each number is written.
Well, one cannot see on which slide a number is written, but one may deduce which numbers are written on which slides. If we label the slides which characters A, B, C, ... as in the figure above, it is obvious that D has number 3, B has number 1, C number 2
and A number 4.
Your task, should you choose to accept it, is to write a program that automates this process.
Input
The input consists of several heap descriptions. Each heap descriptions starts with a line containing a single integer n, the number of slides in the heap. The following n lines contain four integers xmin, xmax, ymin and ymax,
each, the bounding coordinates of the slides. The slides will be labeled as A, B, C, ... in the order of the input.
This is followed by n lines containing two integers each, the x- and y-coordinates of the n numbers printed on the slides. The first coordinate pair will be for number 1, the next pair for 2, etc. No number will lie on a slide boundary.
The input is terminated by a heap description starting with n = 0, which should not be processed.
Output
For each heap description in the input first output its number. Then print a series of all the slides whose numbers can be uniquely determined from the input. Order the pairs by their letter identifier.
If no matchings can be determined from the input, just print the word none on a line by itself.
Output a blank line after each test case.
Sample Input
4 6 22 10 20 4 18 6 16 8 20 2 18 10 24 4 8 9 15 19 17 11 7 21 11 2 0 2 0 2 0 2 0 2 1 1 1 1 0
Sample Output
Heap 1 (A,4) (B,1) (C,2) (D,3) Heap 2 none
关键边 只需要对所有的边 尝试删除这条边 删完之后做匈牙利 如果还能得到最大匹配 ans=n 那么这个边不是关键边 否则就是关键边
PS:这题我写烦了 用有向的好写多了 无向的注意数组范围 2*maxlen 别小了
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<string>
#include<cmath>
#define ff(i,x,y) for(int i=x;i<y;i++)
#define maxlen 30
using namespace std;
int n;
struct nodepoint
{
int x;
int y;
};
struct nodess
{
struct nodepoint lu;
struct nodepoint rd;
};
nodess ss[maxlen];
nodepoint points[maxlen];
//vector<int> G[2 * maxlen]; //与i有边相连的点的集合
int G[2 * maxlen][2 * maxlen];
int check[2*maxlen];
int matching[2*maxlen];
/*
bool dfs(int x)
{
for(int i = 0; i < G[x].size(); i++)
{
int newpos = G[x][i];
if(check[newpos] == 0)
{
check[newpos] = 1;
if(matching[newpos] == -1 || dfs(matching[newpos]) == 1)
{
matching[newpos] = x;
matching[x] = newpos;
return true;
}
}
}//for
return false;
}*/
bool dfs(int x)
{
for(int i = 0; i < 2 * n; i++)
{
if(G[x][i] == 1 && check[i] == 0)
{
check[i] = 1;
if(matching[i] == -1 || dfs(matching[i])==1)
{
matching[i] = x;
matching[x] = i;
return true;
}
}
}//for
return false;
}
int main()
{
//freopen("test.txt", "r", stdin);
int key = 0;
while(1)
{
key++;
memset(G, 0, sizeof G);
//for(int i = 0; i < 2 * maxlen; i++)
//G[i].resize(0);
//输入
scanf("%d", &n);
if(n == 0)
break;
for(int i = 0; i < n; i++)
{
scanf("%d %d %d %d", &ss[i].lu.x, &ss[i].rd.x, &ss[i].lu.y, &ss[i].rd.y);
}
for(int i = 0; i < n; i++)
scanf("%d %d", &points[i].x, &points[i].y);
//构造图
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if((points[j].x >= ss[i].lu.x && points[j].x <= ss[i].rd.x) && (points[j].y >= ss[i].lu.y && points[j].y <= ss[i].rd.y))
{
//G[i].push_back(j + n); //点和面的等价化 面为0~n-1 点为n~2n-1
//G[j + n].push_back(i);
G[i][j + n] = 1;
G[j + n][i] = 1;
}
}
}
memset(matching, -1, sizeof matching);
int ans=0;
for(int k = 0; k < 2 * n; k++)
{
if(matching[k] == -1)
{
memset(check, 0, sizeof check);
check[k] = 1;
if(dfs(k) == true)
ans++;
}
}//求新的ans
//cout<<n<<" "<<ans<<endl;
/*
for(int i = 0; i < n; i++)
{
for(int j = n; j < 2*n; j++)
{
cout<<G[i][j]<<" ";
}
cout<<endl;
}*/
//输出
printf("Heap %d\n", key);
bool ifhave = 0;
for(int i = 0; i < n; i++)
{
for(int j = n; j < 2 * n; j++)
{
if(G[i][j] == 0)
continue;
//int newp = G[i][j];
//vector<int>::iterator it11 = find(G[i].begin(), G[i].end(), newp);
//vector<int>::iterator it22 = find(G[newp].begin(), G[newp].end(), i);
G[i][j] = 0;
G[j][i] = 0;
//G[i].erase(it11);//暂时删掉
//G[newp].erase(it22);
memset(matching, -1, sizeof matching);
int newans = 0;
for(int k = 0; k < 2 * n; k++)
{
if(matching[k] == -1)
{
memset(check, 0, sizeof check);
//check[k] = 1;
if(dfs(k) == 1)
newans++;
}
}//求新的ans
G[i][j] = 1;
G[j][i] = 1;
//G[i].insert(it11,newp);//放回来
//G[newp].insert(it22,i);
if(newans != ans) //关键边
{
//if(ifhave == 1) printf(" ");
printf("(%c,%d) ", 'A' + i, j + 1 - n);
ifhave = 1;
//break;
}
}
}
if(ifhave == 0)
printf("none\n");
else
printf("\n");
printf("\n");
}
//cout<<1<<endl;
return 0;
}
相关文章推荐
- POJ 1486 Sorting Slides(二分图最大匹配:关键边)
- POJ 1486 Sorting Slides 最大二分匹配 匈牙利算法
- POJ 1486 Sorting Slides (二分图关键匹配边)
- POJ 1486 Sorting Slides (二分图关键匹配边)
- POJ 1486 Sorting Slides(二分图最大匹配:关键边)
- POJ - 1486 Sorting Slides 二分图最大匹配(求关键边)
- POJ 1486 Sorting Slides(二分图最大匹配:关键边)
- poj 3041 二分图基础知识+匈牙利算法模版
- POJ 1463 Strategic game (二分图最小覆盖点(匈牙利算法) 或 树形DP)
- POJ-1947-Asteroids-求最小点覆盖数(二分图-匈牙利算法)
- poj1486 sorting slides (二分图最大匹配的唯一性)
- POJ1469(匈牙利算法求二分图最大匹配)
- POJ 1469 COURSES【匈牙利算法入门 二分图的最大匹配 模板题】
- POJ1486 Sorting Slides (二分图求最大匹配)
- POJ 1325 Machine Schedule (二分图最小点集覆盖 匈牙利算法)
- poj 3894 System Engineer (二分图最大匹配--匈牙利算法)
- 求解二分图的最大匹配的匈牙利算法---POJ 1325 Machine Schedule
- POJ 1469 COURSES (二分图最大匹配 匈牙利算法)
- 【二分图|最大匹配】POJ-3041 Asteroids(匈牙利算法dfs、bfs版)
- POJ 1274The Perfect Stall (二分图最大匹配问题,匈牙利算法实现)