题目大意:求所有路径中的最长的边,在这些最长边中找到最小值并输出
思路:我们可以改变dijkstra的dis数组的含义,即所有点到点v的路径上的最小值,例如现在有一条路径为 u->v,我们可以用 dis[u] 和 len(u->v)的长度取最大,再用此时的得到的值,与dis[v]取最小
- #include
- #include
- #include
- #include
- #include
-
- using namespace std;
-
- const int maxn = 220;
-
- const double INF = 1e60;
-
- int n;
- double G[maxn][maxn], d[maxn];
-
- struct Pos {
- int x, y;
- }num[maxn];
-
- double calc(int i, int j) {
- return (sqrt(pow((double)num[i].x-num[j].x, 2)+pow((double)num[i].y-num[j].y, 2)));
- }
-
- double dijkstra() {
- bool vis[maxn];
-
- memset(vis, false, sizeof(vis));
-
- for(int i=0; i
- d[i] = G[0][i];
- }
-
- d[0] = 0;
- vis[0] = true;
-
- for(int i=0; i
-1; i++) { - double m = INF; int x;
- for(int y=0; y
if(!vis[y] && m >= d[y]) m = d[x=y]; - vis[x] = true;
- for(int y=0; y
- if(!vis[y]) {
- double maxx = max(d[x], G[x][y]);
- if(d[y] > maxx) d[y] = maxx;
- }
- }
- }
-
- return d[1];
- }
-
- int main() {
- int cnt = 0;
- while(scanf("%d", &n) == 1) {
- if(n == 0) break;
-
- for(int i=0; i
scanf("%d%d", &num[i].x, &num[i].y); -
- for(int i=0; i
- for(int j=0; j
- G[i][j] = G[j][i] = calc(i, j);
- }
- G[i][i] = 0;
- }
-
- printf("Scenario #%d\nFrog Distance = %.3f\n\n", ++cnt, dijkstra());
- }
-
- return 0;
- }
2.Heavy Transportation(最小路径最大值)
题目大意:N个点,M条边,每条边有权值。求一条1号点到N号点的路径,要求使得路径中的边权最小值最大。
思路:这道题和上一道思路类似,我们可以改变dis数组的含义,在更新dis的过程中与上一道题相反即可
- #include
- #include
-
- using namespace std;
-
- const int N = 1010, M = 1e6+10;
- int h[N], e[M], ne[M], w[M], idx;
- int dis[N],vis[N];
-
- int n,m;
-
- void add(int a,int b,int c){
- e[idx] = b;
- ne[idx] = h[a];
- w[idx] = c;
- h[a] = idx++;
- }
-
- int dj(){
- for(int i=h[1];~i;i=ne[i]){
- int j = e[i];
- dis[j] = w[i];
- }
-
- for(int i=0;i
- int t = -1;
- for(int j=1;j<=n;j++){
- if(!vis[j]&&(t==-1||dis[t]
- t = j;
- }
- }
- vis[t] = 1;
- for(int i = h[t]; ~i ; i = ne[i]){
- int j = e[i];
- int minn = min(w[i],dis[t]);
- dis[j] = max(dis[j],minn);
- }
- }
- return dis[n];
- }
-
- int main(){
-
- int t;
- scanf("%d",&t);
- int cnt=0;
- while(t--){
-
- scanf("%d%d",&n,&m);
- memset(h,-1,sizeof h);
- idx = 0;
- memset(vis,0,sizeof vis);
- memset(dis,-0x3f,sizeof dis);
- while(m--){
- int a ,b,c;
- scanf("%d%d%d",&a,&b,&c);
- add(a,b,c);
- add(b,a,c);
- }
- printf("Scenario #%d:\n%d\n\n",++cnt,dj());
- }
- }
判断正环的题目
思路:如果有正环,那么一定可以循环无限次,让初始值变正
- #include
- #include
- #include
-
- using namespace std;
- const int N = 200, M = N * 2;
-
- int h[N],e[M],ne[M],idx;
- double wr[M],w[M];
-
- int vis[N];
- double dis[N];
- int cnt[N];
- int n,m,s;
- double st;
-
- void add(int a,int b,double r,double c){
- e[idx] = b;
- ne[idx] = h[a];
- wr[idx] = r;
- w[idx] = c;
- h[a] = idx++;
- }
-
- bool spfa(int s)
- {
- queue<int > q;
- q.push(s);
- vis[s] = true;
- dis[s] = st;
-
- for (int i = 1; i <= n; i ++)
- {
- if(i==s)continue;
- q.push(i);
- vis[i] = 1;
- }
-
-
- while (!q.empty())
- {
- int t = q.front();
- q.pop();
- vis[t] = false;
-
- for (int i = h[t]; ~i; i = ne[i])
- {
- int j = e[i];
- if ((dis[t] - w[i]) * wr[i] > dis[j])
- {
- dis[j] = (dis[t] - w[i]) * wr[i];
- cnt[j] = cnt[t] + 1;
- if (cnt[j] >= n) return true;
- if (!vis[j])
- {
- q.push(j);
- vis[j] = true;
- }
- }
- }
- }
-
- return false;
- }
-
-
- int main(){
- cin >> n >> m >> s >>st;
- memset(h,-1,sizeof h);
- while(m--){
- int a,b;
- double r1,r2,c1,c2;
- cin >> a >> b >> r1 >> c1 >> r2 >> c2;
- add(a,b,r1,c1);
- add(b,a,r2,c2);
- }
-
- if(spfa(s)){
- puts("YES");
- }
- else{
- puts("NO");
- }
- }
相关题目:https://vjudge.net/problem/POJ-3259
MPI Maelstrom
MPI Maelstrom - POJ 1502 - Virtual Judge
题目大意:
题目大意:给定一个下三角矩阵,询问从1开始到其他点的最短路径中,最长的那个是多少
思路:其实就是一个很简单的dijkstra的板子题,我们可以一遍dijkstra,跑一遍最短路,找到最大的值输出即可
代码复制的别人的
- #include
- #include
- #include
- using namespace std;
- const int N=110;
- #define MAX 0x7fffffff
- int map[N][N];
- int dis[N],visted[N],n;
- int dijkstra(){
- memset(visted,0,sizeof(visted));
- for(int i=0;i<=n;++i){
- dis[i]=MAX;
- }
- dis[1]=0;
- int pos=1;visted[pos]=1;
- for(int i=1;i<=n;++i){
- for(int j=1;j<=n;++j){
- if(!visted[j]&&map[pos][j]!=MAX&&dis[j]>dis[pos]+map[pos][j])
- dis[j]=dis[pos]+map[pos][j];
- }
- int mmin=MAX;
- for(int j=1;j<=n;++j){
- if(!visted[j]&&dis[j]
- mmin=dis[j];
- pos=j;
- }
- }
- //printf("pos==%d\n",pos);
- visted[pos]=1;
- }
- int mmax=0;
- for(int i=1;i<=n;++i){
- //printf("%d ",dis[i]);
- if(mmax
- mmax=dis[i];
- }
- //cout<
- return mmax;
- }
- int main(){
- //freopen("1.txt","r",stdin);
- while(~scanf("%d",&n)){
- int m;
- char x;
- for(int i=2;i<=n;++i){
- for(int j=1;j
- if(scanf("%d",&m)!=0)
- map[i][j]=map[j][i]=m;
- else{
- map[i][j]=map[j][i]=MAX;
- scanf("%c",&x);
- }
- }
- }
- for(int i=1;i<=n;++i)
- map[i][i]=0;
- int xx=dijkstra();
- printf("%d\n",xx);
- }
- return 0;
- }
Cow Contest(floyd + 传递闭包)
Cow Contest - POJ 3660 - Virtual Judge
题目大意:有N头牛,评以N个等级,各不相同,先给出部分牛的等级的高低关系,问最多能确定多少头牛的等级
思路:如果有一头关系已经确定, 那么他一定与其他所有牛关系已经确定了,即n-1头牛
- #include
- #include
- using namespace std;
- const int N = 110, M = N * 2;
-
- int g[N][N];
-
- int n,m;
-
- void floyd(){
- for(int k=1;k<=n;k++){
- for(int i=1;i<=n;i++){
- for(int j=1;j<=n;j++){
- g[i][j]|=g[i][k]&&g[k][j];
- }
- }
- }
- }
-
- int main(){
- cin >> n >> m;
- while(m--){
- int a, b;
- cin >> a >> b;
- g[a][b] = 1;
- }
-
- floyd();
-
- int res = 0;
- for(int i=1;i<=n;i++){
- int cnt = 0;
- for(int j=1;j<=n;j++){
- if(g[i][j]||g[j][i]) cnt++;
- }
- if(cnt==n-1)res++;
- }
-
- cout << res <
- }
Arbitrage
套利是指利用货币汇率的差异,将一种货币的一个单位转换为同一货币的多个单位。例如,假设1美元买0.5英镑,1英镑买10.0法国法郎,1法国法郎买0.21美元。然后,通过兑换货币,聪明的交易者可以从1美元开始,购买0.5 * 10.0 * 0.21 = 1.05美元,获得5%的利润。
您的工作是编写一个程序,以货币汇率列表作为输入,然后确定是否可能进行套利。
输入:
将包含一个或多个测试用例。每个测试用例的第一行有一个整数n (1<=n<=30),表示不同货币的数量。接下来的n行每一行都包含一种货币的名称。名称中不会出现空格。下一行包含一个整数m,表示接下来的表的长度。最后的m行分别包含源货币的名称ci、表示从ci到cj的汇率的实数rij和目标货币的名称cj。没有出现在表格中的交易是不可能的。
测试用例通过空行彼此分开。对于n,输入以0(0)的值结束
思路:和上面找正环的思路差不多
- //floyed
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- using namespace std;
- int n,m;
- double dist[40][40];
- map
int> money; -
- void init()
- {
- for(int i = 0;i < n;i++) {
- for(int j = 0;j < n;j++){
- if(i == j) dist[i][j] = 1;
- else dist[i][j] = 0;
- }
- }
- }
-
- void floyd()
- {
- for(int k = 0;k < n;k++) {
- for(int i = 0;i < n;i++) {
- for(int j = 0;j < n;j++) {
- if(dist[i][j] < dist[i][k] * dist[k][j])
- dist[i][j] = dist[i][k] * dist[k][j];
- }
- }
- }
- }
-
- int main()
- {
- int cas = 1;
- string s,ss;
- double r;
- while(~scanf("%d",&n) &&n) {
- init();
- for(int i = 0;i < n;i++) {
- cin >> s;
- money[s] = i;
- }
- cin >> m;
-
- for(int i = 0;i < m;i++) {
- cin >> s >> r >> ss;
- dist[money[s] ][money[ss] ] = r;
- }
- floyd();
- printf("Case %d: ",cas++);
- for(int i = 0;i < n;i++) {
- if(dist[i][i] > 1) {
- cout << "Yes" << endl;
- break;
- }
- else if(i == n - 1)
- cout << "No" <
- }
- }
- return 0;
- }
差分约束见另外一篇文章
-
相关阅读:
Netty 进阶学习(十)-- 协议设计与解析
JavaScript 63 JavaScript 对象 63.4 JavaScript 显示对象
Eclipse连接Mysql超详细教程
JSR303校验,分组校验,自定义注解校验,全局异常处理
C# 压缩图片
【快应用】网络图片保存到相册失败案例
lftp服务与http服务(包含scp服务)详解
Unity开发过程中的一些小知识点
Linux中使用Docker安装ElasticSearch7.10.x集群
uniapp搜索功能
-
原文地址:https://blog.csdn.net/qq_52280112/article/details/126173559