BZOJ 1050 旅行comf 并查集+枚举下界

题目链接:

https://www.lydsy.com/JudgeOnline/problem.php?id=1050

题目大意:

给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。

思路:

枚举最小的边,逐步按照权值从小到大将边加入并查集中,直到s-t连通为止。

每次保留最小的ans(分数)即可。

  1 #include<bits/stdc++.h>
  2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
  3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
  4 #define Min(a, b) ((a) < (b) ? (a) : (b))
  5 #define Mem(a) memset(a, 0, sizeof(a))
  6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
  7 #define MID(l, r) ((l) + ((r) - (l)) / 2)
  8 #define lson ((o)<<1)
  9 #define rson ((o)<<1|1)
 10 #define Accepted 0
 11 #pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
 12 using namespace std;
 13 inline int read()
 14 {
 15     int x=0,f=1;char ch=getchar();
 16     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
 17     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 18     return x*f;
 19 }
 20 
 21 typedef long long ll;
 22 const int maxn = 10000 + 10;
 23 const int MOD = 1000000007;//const引用更快,宏定义也更快
 24 const int INF = 1e9 + 7;
 25 const double eps = 1e-6;
 26 
 27 struct edge
 28 {
 29     int u, v, w;
 30     edge(){}
 31     edge(int u, int v, int w):u(u), v(v), w(w){}
 32     bool operator < (const edge& a)const
 33     {
 34         return w < a.w;
 35     }
 36 };
 37 vector<edge>e;
 38 int p[maxn];
 39 vector<int>G[maxn];
 40 void addedge(int u, int v, int w)
 41 {
 42     e.push_back(edge(u, v, w));
 43     G[u].push_back(e.size() - 1);
 44     e.push_back(edge(v, u, w));
 45     G[v].push_back(e.size() - 1);
 46 }
 47 int Find(int x)
 48 {
 49     return x == p[x] ? x : p[x] = Find(p[x]);
 50 }
 51 struct node
 52 {
 53     int a, b;
 54     node(){}
 55     node(int A, int B)
 56     {
 57         int g = __gcd(A, B);
 58         a = A / g, b = B / g;
 59     }
 60     bool operator < (const node& tmp)const
 61     {
 62         return a * tmp.b < b * tmp.a;
 63     }
 64 };
 65 
 66 int main()
 67 {
 68     int n, m, u, v, w, s, t;
 69     scanf("%d%d", &n, &m);
 70     while(m--)
 71     {
 72         scanf("%d%d%d", &u, &v, &w);
 73         addedge(u, v, w);
 74     }
 75     scanf("%d%d", &s, &t);
 76     sort(e.begin(), e.end());
 77     m = e.size();
 78     node ans(1, 0);//最大
 79     for(int start = 0; start < m; start++)//枚举下限
 80     {
 81         for(int i = 1; i <= n; i++)p[i] = i;//初始化并查集
 82         int cnt = -INF;
 83         for(int i = start; i < m; i++)
 84         {
 85             int u = e[i].u, v = e[i].v, w = e[i].w;
 86             u = Find(u);
 87             v = Find(v);
 88             p[u] = v;
 89             if(Find(s) == Find(t))
 90             {
 91                 cnt = w;
 92                 break;
 93             }
 94         }
 95         if(cnt == -INF)
 96         {
 97             break;
 98         }
 99         ans = min(ans, node(cnt, e[start].w));
100     }
101     if(ans.a == 1 && ans.b == 0)puts("IMPOSSIBLE\n");
102     else if(ans.b != 1)printf("%d/%d\n", ans.a, ans.b);
103     else printf("%d\n", ans.a);
104     return Accepted;
105 }

 

posted @ 2018-09-20 00:43  _努力努力再努力x  阅读(207)  评论(0编辑  收藏  举报