Atcoder 329 Dictionary (拓扑排序/floyd) HQG_AC的博客

本文介绍了一种用于判断一组字符串是否能被视为字典顺序排列的算法。通过对比相邻字符串找到不同字符并建立字符间的顺序关系,利用弗洛伊德算法检查是否存在矛盾的顺序关系。

A - Dictionary

Time limit : 20sec / Memory limit : 256MB

Problem Statement

We found a dictionary of the Ancient Civilization Mayo (ACM) during excavation of the ruins. After analysis of the dictionary, we revealed they used a language that had not more than 26 letters. So one of us mapped each letter to a different English alphabet and typed all the words in the dictionary into a computer.

How the words are ordered in the dictionary, especially whether they are ordered lexicographically, is an interesting topic to many people. As a good programmer, you are requested to write a program to judge whether we can consider the words to be sorted in a lexicographical order.

Note: In a lexicographical order, a word always precedes other words it is a prefix of. For example, ab precedes abc, abde, and so on.

Input

The input consists of multiple datasets. Each dataset is formatted as follows:

n
string1

stringn

Each dataset consists of n+1 lines. The first line of each dataset contains an integer that indicates n (1≤n≤500). The i-th line of the following n lines contains stringi, which consists of up to 10 English lowercase letters.

The end of the input is 0, and this should not be processed.

Output

Print either yes or no in a line for each dataset, in the order of the input. If all words in the dataset can be considered to be ordered lexicographically, print yes. Otherwise, print no.

Sample Input

4
cba
cab
b
a
3
bca
ab
a
5
abc
acb
b
c
c
5
abc
acb
c
b
b
0

Output for the Sample Input
yes
no
yes
no

Source name

JAG Practice Contest for ACM-ICPC Asia Regional 2012

题意:给你n个字符串,让你判断这些单词是否属于一种顺序(自行定义)

这一看就是一道拓扑排序裸题,但我们今天要讲一讲别的算法

解析:

先读入,判断Si]和S[i+1]在哪里不相同,
我们那Sample Input 1 的第一个举例

4
cba
cab
b
a

a数组表示i字符在字典中是排在j之前(1)还是之后(0)

初始都为0

首先判断S[1]和S[2],在第2位不同,a[‘b’][‘a’]=1
判断S[2]和S[3],第1位不同,a[‘c’][‘a’]=1
同理 a[‘b][‘a’]=1

之后跑floyd。

如果 a[i][i]=1,即出现环 out “no”
else out “yes” ;

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <bitset>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <vector>
#include <string>
#include <functional>

using namespace std ;

const int eps=1e-6 ;
const int inf=0x3f3f3f3f ;

#define mp make_pair
#define pb push_back
#define first fi
#define second se
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define REP(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)

typedef unsigned long long ull ;
typedef long long ll ;

const int N = 510 ;
const int L = 20 ;

int n ;
char str[N][L] ; 
int len[N],G[N][N] ;

int main(){
    while (scanf("%d",&n)!=EOF && n!=0){
        rep(i,1,n){
            scanf("%s",str[i]); 
            len[i]=strlen(str[i]) ;
        }
        memset(G,0,sizeof(G)) ;
        int ans=1 ; 
        rep(i,1,n-1){
            int j=0 ;
            while (j<len[i] && j<len[i+1] && str[i][j]==str[i+1][j]) j++ ;
            if (j<len[i] && j==len[i+1]){
                ans=0 ;
                break ;
            }
            if (j<len[i] && j<len[i+1]) G[str[i][j]-'a'][str[i+1][j]-'a']=1 ;
        }
        rep(k,0,26) rep(i,0,26) rep(j,0,26) G[i][j]|=(G[i][k]&G[k][j]) ;
        rep(i,0,26) if (G[i][i]) ans=0;
        printf("%s\n",ans?"yes":"no") ;
    }
    return 0 ;
}

#include <iostream>
#include <cstring>
using namespace std;
int n;
string s[505];
bool f[30][30];
bool fulfill(string a,string b)
{
    int mn=min(a.size(),b.size());
    for (int i=0;i<mn;++i) if (a[i]!=b[i]) return f[a[i]-'a'][b[i]-'a']=true;
    if (a.size()>b.size()) return false;
    return true;
}
int main()
{
    while (cin>>n && n)
    {
        memset(f,0,sizeof(f));
        for (int i=0;i<n;++i) cin>>s[i];
        for (int i=0;i<n-1;++i)
        {
            if (!fulfill(s[i],s[i+1]))
            {
                cout<<"no\n";
                goto ends;
            }
        }
        for (int k=0;k<30;++k) for (int i=0;i<30;++i) for (int j=0;j<30;++j) f[i][j]=f[i][j]|(f[i][k]&f[k][j]);
        for (int i=0;i<30;++i) for (int j=0;j<30;++j) if (f[i][j] && f[j][i])
        {
            cout<<"no\n";
            goto ends;
        }
        cout<<"yes\n";
        ends:;
    }
    return 0;
}
要实现你提出的 **性能对比测试**,我们需要: 1. 生成稠密图(节点数从 100 到 1000,步进 100); 2. 分别运行 Floyd-Warshall 和 Dijkstra(单源); 3. 统计每个规模下的运行时间; 4. 输出结果并绘制折线图。 --- ## ✅ 完整测试代码(`benchmark.c`) ```c #include "_floyd_spf_.h" #include "_graph_operate_.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> // 生成稠密图(节点数为 n,边权值随机) void generate_dense_graph(Graph* graph, int n) { char ip[32]; for (int i = 0; i < n; i++) { snprintf(ip, sizeof(ip), "10.0.0.%d", i); graph_add_node(graph, ip); } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i != j) { int weight = rand() % 100 + 1; graph_add_edge(graph, get_ip(graph, i), get_ip(graph, j), weight); } } } } // 生成 IP 地址字符串 const char* generate_ip(int index) { static char ip[32]; snprintf(ip, sizeof(ip), "10.0.0.%d", index); return ip; } // 主测试函数 int main() { FILE* fp = fopen("results.csv", "w"); if (!fp) { printf("无法创建文件 results.csv\n"); return 1; } fprintf(fp, "Node Count,Floyd-Warshall (ms),Dijkstra (ms)\n"); for (int node_count = 100; node_count <= 1000; node_count += 100) { Graph* graph = graph_init(); generate_dense_graph(graph, node_count); const char* src_ip = generate_ip(0); // 测试 Floyd-Warshall clock_t start = clock(); PathTableEntry* floyd_table = compute_all_shortest_paths(graph); clock_t end = clock(); double floyd_time = (double)(end - start) * 1000 / CLOCKS_PER_SEC; // 测试 Dijkstra start = clock(); PathTableEntry* dijkstra_table = dijkstra(graph, src_ip); end = clock(); double dijkstra_time = (double)(end - start) * 1000 / CLOCKS_PER_SEC; // 保存结果 printf("节点数:%d | Floyd-Warshall: %.2f ms | Dijkstra: %.2f ms\n", node_count, floyd_time, dijkstra_time); fprintf(fp, "%d,%.2f,%.2f\n", node_count, floyd_time, dijkstra_time); // 释放资源 free_path_table(floyd_table); free_path_table(dijkstra_table); free_graph(graph); } fclose(fp); printf("结果已保存到 results.csv\n"); return 0; } ``` --- ## ✅ 编译与运行方式 ```bash # 编译(假设你已有 graph_operate.c、floyd_spf.c、dijkstra_spf.c) gcc -o benchmark benchmark.c graph_operate.c floyd_spf.c dijkstra_spf.c uthash.h -lm # 运行 ./benchmark ``` --- ## ✅ 输出文件 `results.csv` 内容格式如下: ``` Node Count,Floyd-Warshall (ms),Dijkstra (ms) 100,15.23,3.45 200,60.12,7.89 300,135.45,12.34 ... 1000,1200.00,45.67 ``` --- ## ✅ Python 绘图脚本(`plot_results.py`) ```python import pandas as pd import matplotlib.pyplot as plt # 读取数据 df = pd.read_csv("results.csv") # 设置中文字体 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False # 绘图 plt.figure(figsize=(10, 6)) plt.plot(df["Node Count"], df["Floyd-Warshall (ms)"], label="Floyd-Warshall", marker='o') plt.plot(df["Node Count"], df["Dijkstra (ms)"], label="Dijkstra", marker='s') plt.title("Floyd-Warshall vs Dijkstra 性能对比") plt.xlabel("节点数量") plt.ylabel("运行时间 (ms)") plt.grid(True) plt.legend() plt.tight_layout() plt.show() ``` --- ## ✅ 预期结果图(折线图) - **Floyd-Warshall** 曲线呈立方增长(O()); - **Dijkstra** 曲线呈 O() 增长; - 在节点数较少时,两者差距不大; - 节点数越多,Dijkstra 明显优于 Floyd-Warshall。 --- ## ✅ 后续建议 - 使用优先队列优化 Dijkstra; - 使用稀疏图测试; - 多次取平均值提高准确性; - 支持并发测试(多线程); - 支持导出 JSON、XML 格式。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值